{"record":{"id":"3541989a07e77499","repo":"jackwener/OpenCLI","slug":"manus-credits-returned-a-malformed-api-payload","errorCode":null,"errorMessage":"Manus credits returned a malformed API payload","messagePattern":"Manus credits returned a malformed API payload","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/manus/credits.js","lineNumber":26,"sourceCode":"    access: 'read',\n    description: 'Show Manus credit balance and refresh details.',\n    domain: MANUS_DOMAIN,\n    strategy: Strategy.COOKIE,\n    browser: true,\n    siteSession: 'persistent',\n    navigateBefore: true,\n    args: [],\n    columns: ['Field', 'Value'],\n    func: async (page) => {\n        await ensureOnManus(page);\n\n        const c = requireObject(await page.evaluate(`(async () => {\n            ${MANUS_API_CALL_JS}\n            return callManusAPI('user.v1.UserService/GetAvailableCredits', {});\n        })()`), 'credits');\n\n        if (!['totalCredits', 'freeCredits', 'periodicCredits', 'refreshCredits'].some((key) => c[key] != null)) {\n            throw new CommandExecutionError('Manus credits returned a malformed API payload');\n        }\n        return [\n            { Field: 'Total Credits', Value: c.totalCredits ?? '—' },\n            { Field: 'Free Credits', Value: c.freeCredits ?? '—' },\n            { Field: 'Periodic Credits', Value: c.periodicCredits ?? '—' },\n            { Field: 'Pro Monthly Credits', Value: c.proMonthlyCredits ?? '—' },\n            { Field: 'Refresh Credits', Value: c.refreshCredits ?? '—' },\n            { Field: 'Max Refresh Credits', Value: c.maxRefreshCredits ?? '—' },\n            { Field: 'Next Refresh', Value: c.nextRefreshTime || '—' },\n            { Field: 'Refresh Interval', Value: c.refreshInterval || '—' },\n        ];\n    },\n});\n","sourceCodeStart":8,"sourceCodeEnd":40,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/manus/credits.js#L8-L40","documentation":"The manus credits command calls user.v1.UserService/GetAvailableCredits and throws this CommandExecutionError when the response object contains none of the expected credit fields (totalCredits, freeCredits, periodicCredits, refreshCredits). It means the API responded but with a payload the command cannot interpret as credits data.","triggerScenarios":"GetAvailableCredits returns 200/OK with a body lacking all four credit keys — e.g. an empty object, an error envelope, or a response whose field names changed after a Manus API update.","commonSituations":"Manus renamed or restructured credit fields in a newer API version; the session is valid but the account tier doesn't expose credit fields; a gateway/anti-bot layer returned a 200 HTML or challenge payload instead of the RPC result; RPC responded with an error status the wrapper still surfaced as an object.","solutions":["Refresh the session by re-running the manus auth/login flow, then retry the credits command","Log the raw `c` object from the evaluate result to see what GetAvailableCredits actually returned","Check whether Manus changed the GetAvailableCredits response schema and update the expected keys in clis/manus/credits.js","Retry later — transient gateway/bot-challenge responses can masquerade as malformed payloads"],"exampleFix":"// before\nif (!['totalCredits', 'freeCredits', 'periodicCredits', 'refreshCredits'].some((key) => c[key] != null)) {\n    throw new CommandExecutionError('Manus credits returned a malformed API payload');\n}\n// after (include raw payload for diagnosability)\nif (!['totalCredits', 'freeCredits', 'periodicCredits', 'refreshCredits'].some((key) => c[key] != null)) {\n    throw new CommandExecutionError(`Manus credits returned a malformed API payload: ${JSON.stringify(c).slice(0, 500)}`);\n}","handlingStrategy":"validation","validationCode":"const credits = await page.evaluate(`(async () => {\n  ${MANUS_API_CALL_JS}\n  return callManusAPI('user.v1.UserService/GetAvailableCredits', {});\n})()`);\nconst keys = ['totalCredits','freeCredits','periodicCredits','refreshCredits'];\nif (!credits || !keys.some(k => credits[k] != null)) {\n  throw new Error('GetAvailableCredits payload lacks credit fields: ' + JSON.stringify(credits));\n}","typeGuard":"function hasCreditFields(c) {\n  return c != null && typeof c === 'object' &&\n    ['totalCredits','freeCredits','periodicCredits','refreshCredits'].some(k => c[k] != null);\n}","tryCatchPattern":"try {\n  const rows = await manusCredits();\n} catch (e) {\n  if (e instanceof CommandExecutionError && /malformed API payload/.test(e.message)) {\n    await refreshManusSession();\n    return manusCredits(); // one retry after re-auth\n  }\n  throw e;\n}","preventionTips":["Keep a current session — a stale session can yield error envelopes instead of credit data","When Manus ships API updates, diff the GetAvailableCredits response against expected keys","Validate the payload shape before formatting output rows","Capture the raw payload in logs to distinguish schema drift from bot-challenge responses"],"tags":["api-schema","credits","payload-validation","browser-automation"],"backgroundTag":"unexpected-api-response-shape","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}