{"record":{"id":"747cd8242deaf23e","repo":"jackwener/OpenCLI","slug":"malformed-drafttype-draft-payload","errorCode":null,"errorMessage":"Malformed ${draftType} draft payload","messagePattern":"Malformed (.+?) draft payload","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/xiaohongshu/draft-utils.js","lineNumber":132,"sourceCode":"        return {\n          ok: true,\n          entries: allRows.map((row, index) => ({ key: allKeys[index] ?? index, row })),\n        };\n      } catch (error) {\n        return { ok: false, error: String(error && error.message || error) };\n      }\n    })()\n  `;\n}\n\nexport async function readDraftEntries(page, draftType) {\n    const storeName = STORE_NAME_MAP[draftType];\n    const payload = unwrapBrowserResult(await page.evaluate(draftReadScript(storeName)));\n    if (!payload?.ok) {\n        throw new CommandExecutionError(payload?.error || `Failed to read ${draftType} drafts`);\n    }\n    if (!Array.isArray(payload.entries)) {\n        throw new CommandExecutionError(`Malformed ${draftType} draft payload`);\n    }\n    return payload.entries;\n}\n\nexport function draftNotFound(id, draftType, command) {\n    return new EmptyResultError(\n        command,\n        `Draft ${id} was not found in ${draftType} drafts. Run opencli xiaohongshu drafts --type ${draftType} to list current ids.`,\n    );\n}\n","sourceCodeStart":114,"sourceCodeEnd":143,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/xiaohongshu/draft-utils.js#L114-L143","documentation":"readDraftEntries validates that the in-page script's payload contains an entries array. If payload.ok was true but payload.entries is missing or not an Array, it throws CommandExecutionError with 'Malformed <draftType> draft payload'. This is a contract check against the browser-side result.","triggerScenarios":"page.evaluate(draftReadScript(storeName)) returns { ok: true } but entries is undefined, null, or a non-array (e.g. an object or single item) because the in-page script returned the wrong shape.","commonSituations":"Site script changes altering the draft store schema, a partial/empty store returning undefined, or a hand-edited draftReadScript that returns the store value directly instead of wrapping it in an entries array.","solutions":["Inspect the actual payload shape by evaluating draftReadScript(storeName) in DevTools on the drafts page","Update draftReadScript to always return { ok: true, entries: [...] }","Confirm the logged-in account actually has the draft store present; empty stores should still return []","Re-check STORE_NAME_MAP mapping matches the current site store names"],"exampleFix":"// before (in-page script)\nreturn { ok: true, entries: store.all() };\n// after (guarantee array)\nconst all = store.all ? store.all() : [];\nreturn { ok: true, entries: Array.isArray(all) ? all : [all] };","handlingStrategy":"type-guard","validationCode":"const payload = unwrapBrowserResult(await page.evaluate(draftReadScript(storeName)));\nif (!payload?.ok || !Array.isArray(payload.entries)) throw new Error('draft payload malformed');","typeGuard":"function hasEntries(p) { return !!p && typeof p === 'object' && p.ok === true && Array.isArray(p.entries); }","tryCatchPattern":"try {\n  const entries = await readDraftEntries(page, draftType);\n} catch (err) {\n  if (err instanceof CommandExecutionError && err.message.includes('Malformed')) {\n    // dump raw payload for debugging, update draftReadScript to normalize to array\n  } else throw err;\n}","preventionTips":["Always return { ok:true, entries: [...] } from the in-page script, coercing to array","Pin/verify the site's store schema after site updates","Add a DevTools smoke test of draftReadScript output"],"tags":["browser-automation","schema","drafts"],"backgroundTag":"payload-schema-mismatch","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}