{"record":{"id":"1fbf7d54f3f14ac8","repo":"jackwener/OpenCLI","slug":"manus-skills-returned-a-malformed-api-payload","errorCode":null,"errorMessage":"Manus skills returned a malformed API payload","messagePattern":"Manus skills returned a malformed API payload","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/manus/skills.js","lineNumber":30,"sourceCode":"    browser: true,\n    siteSession: 'persistent',\n    navigateBefore: true,\n    args: [],\n    columns: ['ID', 'Name', 'Description', 'Source'],\n    func: async (page) => {\n        await ensureOnManus(page);\n\n        const data = requireObject(await page.evaluate(`(async () => {\n            ${MANUS_API_CALL_JS}\n            return callManusAPI('skill.v1.SkillService/ListSkills', {});\n        })()`), 'skills');\n\n        const rows = [];\n\n        const hasUserSkills = Object.prototype.hasOwnProperty.call(data, 'userAddedSkills');\n        const hasSystemSkills = Object.prototype.hasOwnProperty.call(data, 'systemSkills') || Object.prototype.hasOwnProperty.call(data, 'skills');\n        if (!hasUserSkills && !hasSystemSkills) {\n            throw new CommandExecutionError('Manus skills returned a malformed API payload');\n        }\n\n        const userSkills = hasUserSkills ? requireArray(data.userAddedSkills, 'user skills') : [];\n        for (const [index, s] of userSkills.entries()) {\n            rows.push({\n                ID: requireString(s?.id || s?.uid, `user skill ${index + 1}`),\n                Name: requireString(s?.name, `user skill ${index + 1}`),\n                Description: (s.description || '—').slice(0, 80),\n                Source: 'user',\n            });\n        }\n\n        const systemSkills = Object.prototype.hasOwnProperty.call(data, 'systemSkills')\n            ? requireArray(data.systemSkills, 'system skills')\n            : (Object.prototype.hasOwnProperty.call(data, 'skills') ? requireArray(data.skills, 'system skills') : []);\n        for (const [index, s] of systemSkills.entries()) {\n            rows.push({\n                ID: requireString(s?.id || s?.uid, `system skill ${index + 1}`),","sourceCodeStart":12,"sourceCodeEnd":48,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/manus/skills.js#L12-L48","documentation":"The `manus skills` command calls `skill.v1.SkillService/ListSkills` and expects the response object to contain at least one of the known skill-list keys: `userAddedSkills`, `systemSkills`, or `skills`. If the payload has none of these keys, the code concludes the API contract changed or the response is not a real skills payload and throws this CommandExecutionError. It is a defensive schema check against Manus API shape drift.","triggerScenarios":"The ListSkills endpoint returns a payload with no `userAddedSkills`/`systemSkills`/`skills` key — e.g. Manus renamed or restructured the response fields, an auth/anti-bot interstitial returned HTML or a different JSON body that still parsed as an object, or the response is an empty object due to a server-side change.","commonSituations":"Manus shipping a frontend/API update that renames response fields; the CLI's cookie-session page.evaluate getting an unexpected logged-out or error JSON response; regional/API-version differences in the skill service.","solutions":["Re-login to Manus in the browser profile and retry, to rule out an auth/error response masquerading as a payload.","Update the CLI to the latest version so it matches the current Manus ListSkills response schema.","Inspect the raw response (call ListSkills via devtools on manus.im while logged in) to confirm the field names; report/file an issue if the schema changed.","Wait and retry if Manus is mid-deploy; transient API instability can yield odd payloads."],"exampleFix":"// payload Manus actually returned after a schema change\n{\"items\": [...]}  // no userAddedSkills/systemSkills/skills -> throws\n\n// fix: update the CLI or patch the key check\n// before\nif (!hasUserSkills && !hasSystemSkills) throw new CommandExecutionError('Manus skills returned a malformed API payload');\n// after\nconst hasItems = Object.prototype.hasOwnProperty.call(data, 'items');\nif (!hasUserSkills && !hasSystemSkills && !hasItems) throw new CommandExecutionError('Manus skills returned a malformed API payload');","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"function isSkillsPayload(d) {\n  return !!d && typeof d === 'object' &&\n    ['userAddedSkills', 'systemSkills', 'skills'].some(k => Object.prototype.hasOwnProperty.call(d, k));\n}","tryCatchPattern":"try {\n  const rows = await run('manus skills');\n} catch (e) {\n  if (/malformed API payload/.test(e.message)) {\n    console.error('Manus API schema may have changed — update the CLI and re-login, then retry.');\n  } else throw e;\n}","preventionTips":["Keep the CLI updated so its expected ListSkills schema tracks Manus changes.","Ensure the browser profile is logged in — an auth/error JSON body can masquerade as a payload.","Before scripting, spot-check the raw ListSkills response in devtools while logged in.","If a schema change breaks the CLI, report it rather than silently treating it as no skills."],"tags":["schema-change","api-payload","malformed-response","cli"],"backgroundTag":"unexpected-api-response-shape","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}