{"record":{"id":"a68378f71f9920a6","repo":"jackwener/OpenCLI","slug":"label-returned-an-unexpected-payload-shape-exp-a68378","errorCode":null,"errorMessage":"${label} returned an unexpected payload shape; expected an array.","messagePattern":"(.+?) returned an unexpected payload shape; expected an array\\.","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/dongchedi/utils.js","lineNumber":117,"sourceCode":"    if (isFallbackShell(pp)) {\n        throw new CommandExecutionError(\n            `dongchedi ${contextHint}`,\n            'Dongchedi served its empty fallback shell — the id may not exist or the URL form changed.',\n        );\n    }\n    return pp;\n}\n\nexport function assertPlainObject(value, label) {\n    if (!value || typeof value !== 'object' || Array.isArray(value)) {\n        throw new CommandExecutionError(`${label} returned an unexpected payload shape; expected an object.`);\n    }\n    return value;\n}\n\nexport function requireArray(value, label) {\n    if (!Array.isArray(value)) {\n        throw new CommandExecutionError(`${label} returned an unexpected payload shape; expected an array.`);\n    }\n    return value;\n}\n\nexport function requireStableId(value, label) {\n    const id = String(value ?? '').trim();\n    if (!/^\\d+$/.test(id) || id === '0') {\n        throw new CommandExecutionError(`${label} did not include a stable numeric id.`);\n    }\n    return id;\n}\n\nexport function requireText(value, label) {\n    const text = clean(value);\n    if (!text) {\n        throw new CommandExecutionError(`${label} did not include a stable text value.`);\n    }\n    return text;","sourceCodeStart":99,"sourceCodeEnd":135,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/dongchedi/utils.js#L99-L135","documentation":"A CommandExecutionError thrown by requireArray (clis/dongchedi/utils.js:117), a schema guard called by parseKoubei, parseModels, and the sameLevelAverage/data parsing paths. It fires when a pageProps field expected to be a JSON array arrives as null, an object, or a scalar — typically because the upstream block is missing or its shape changed.","triggerScenarios":"Running dongchedi koubei, models, or score commands when the reviews/models/score-list block in pageProps is null (no data for the item), became an object after a site schema change, or the wrong pageProps key is being read.","commonSituations":"Querying cars with zero reviews/owner scores (the list block is genuinely absent); a Dongchedi redeploy restructuring a list field; stale test fixtures passing objects where the site sends arrays.","solutions":["Inspect the live pageProps key being passed to requireArray and confirm its actual type; update the parser key or shape handling if the site changed.","For items that legitimately lack the list (no reviews/scores), handle the empty case before calling the parser.","Catch CommandExecutionError in the command and return an empty table with a notice instead of crashing.","Fix test fixtures to mirror the real array-typed SSR payload."],"exampleFix":"// before\nconst list = requireArray(pp.reviewList, 'koubei reviews'); // throws when absent\n// after\nconst list = Array.isArray(pp.reviewList) ? requireArray(pp.reviewList, 'koubei reviews') : [];","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"function isArray(v) {\n  return Array.isArray(v);\n}","tryCatchPattern":"if (!Array.isArray(pp.reviewList)) {\n  return []; // treat absent list (e.g. no reviews) as empty, not an error\n}\nconst list = requireArray(pp.reviewList, 'koubei reviews');","preventionTips":["Check Array.isArray on list fields before parsing.","Expect absent lists for items with no reviews/scores and handle gracefully.","Update parser key paths after site schema changes.","Keep test fixtures array-typed like the live payloads."],"tags":["schema-validation","parsing","dongchedi","type-mismatch"],"backgroundTag":"schema-validation-failed","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}