Request body invalid while trying Storage (kvs)

I’ve looked for this error in the community and I can’t find why I keep getting it. I’m building a Jira app with Forge Custom UI and I’m trying to store and retrieve some data for the app. The error I’m getting is:

Error invoking save-view: Error: There was an error invoking the function - Provided request body is invalid
    at invoke (https://jira-frontend-bifrost.prod-east.frontend.public.atl-paas.net/assets/async-forge-ui-full-page-extension.23b6c6b5.js:82:46361)
    at async https://jira-frontend-bifrost.prod-east.frontend.public.atl-paas.net/assets/async-forge-ui-full-page-extension.23b6c6b5.js:82:79730

Error: There was an error invoking the function - Provided request body is invalid
    at he.error (https://forge.cdn.prod.atlassian-dev.net/global-bridge.js:2:131452)
    at Object.<anonymous> (https://forge.cdn.prod.atlassian-dev.net/global-bridge.js:2:139225)
    at JSON.parse (<anonymous>)
    at Oe.o (https://forge.cdn.prod.atlassian-dev.net/global-bridge.js:2:139084)
    at Oe (https://forge.cdn.prod.atlassian-dev.net/global-bridge.js:2:139237)
    at Te.s.on (https://forge.cdn.prod.atlassian-dev.net/global-bridge.js:2:143897)
    at Te (https://forge.cdn.prod.atlassian-dev.net/global-bridge.js:2:144034)
    at https://forge.cdn.prod.atlassian-dev.net/global-bridge.js:2:150020
    at e.try (https://forge.cdn.prod.atlassian-dev.net/global-bridge.js:2:122504)
    at https://forge.cdn.prod.atlassian-dev.net/global-bridge.js:2:149817

Then the frontend portion where the save and read functions are called is:

const loadViews = async () => {
        console.log("Loading views from storage...");
        const savedViews = await invoke('load-views');
        console.log("Loaded views:", savedViews);
        return savedViews || [];
    };

    const handleSaveView = async (viewName) => {
        console.log("handleSaveView called with name:", viewName);
        const viewConfiguration = {
            projectOrder: projectData.map(p => p.key),
            milestoneSelection: milestoneSelection
        };
        try {
            await invoke('save-view', { viewName, viewConfiguration: JSON.stringify(viewConfiguration) });
        } catch (e) {
            console.error("Error invoking save-view:", e);
        }
        loadViews().then(savedViews => {
            setViews(savedViews);
        });
        setSelectedView(viewName);
        setIsSaveViewModalOpen(false);
    };

And here’s the portion of the backend implementation:

import Resolver from '@forge/resolver';
import api, { route } from '@forge/api';
import { kvs } from '@forge/kvs';

resolver.define('load-views', async () => {
    console.log("Loading views from storage (backend)...");
    const savedViews = await kvs.entity('roadmap-views').get('all-views');
    console.log("Loaded views (backend):", savedViews);
    return savedViews || [];
});

resolver.define('save-view', async ({ payload }) => {
    const { viewName, viewConfiguration } = payload;
    const parsedConfiguration = JSON.parse(viewConfiguration);
    console.log("Saving view configuration (backend):", viewName);

    // Get existing views
    let allViews = await kvs.entity('roadmap-views').get('all-views');
    if (!allViews) {
        allViews = [];
    }

    // Add or update the view
    const newView = { name: viewName, configuration: parsedConfiguration };
    const existingViewIndex = allViews.findIndex(v => v.name === viewName);
    if (existingViewIndex > -1) {
        allViews[existingViewIndex] = newView;
    } else {
        allViews.push(newView);
    }

    // Save the updated list of views
    await kvs.entity('roadmap-views').set('all-views', allViews);

    return { success: true };
});

Could someone help me to point me to what I’m doing wrong? I’m not sure if the payload is not properly shared to the backend, or if the data is not formated correctly

1 Like