{"record":{"id":"02cf8c32bdf423b4","repo":"jackwener/OpenCLI","slug":"label-returned-an-unexpected-payload-shape-exp-02cf8c","errorCode":null,"errorMessage":"${label} returned an unexpected payload shape; expected an object.","messagePattern":"(.+?) returned an unexpected payload shape; expected an object\\.","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/autohome/utils.js","lineNumber":120,"sourceCode":"    }\n    return n;\n}\n\nexport function requireStableId(value, label) {\n    const id = String(value ?? '').trim();\n    if (!/^\\d+$/.test(id)) throw new CommandExecutionError(`${label} did not include a stable numeric id.`);\n    return id;\n}\n\nexport function requireText(value, label) {\n    const text = clean(value);\n    if (!text) throw new CommandExecutionError(`${label} did not include a stable text value.`);\n    return text;\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\n/** Fetch an Autohome page as text. The grade + koubei pages are UTF-8. */\nexport async function ahFetch(url, contextHint) {\n    let resp;\n    try {\n        resp = await fetch(url, {\n            headers: {\n                'User-Agent': UA,\n                Referer: `${AH_BASE}/`,\n                'Accept-Language': 'zh-CN,zh;q=0.9',\n            },\n        });\n    } catch (err) {\n        throw new CommandExecutionError(`autohome ${contextHint} network error: ${err?.message || err}`);\n    }","sourceCodeStart":102,"sourceCodeEnd":138,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/autohome/utils.js#L102-L138","documentation":"assertPlainObject() throws CommandExecutionError when `value` is null, not an object, or an array — i.e., the fetched payload (`label`) is not the expected object shape. It protects downstream property access from shape changes in scraped/API data.","triggerScenarios":"extractPageProps or similar returns null/undefined because __NEXT_DATA__ was absent; a JSON endpoint returns an array or string; a failed fetch produced a non-object placeholder.","commonSituations":"Autohome changing their Next.js data format; region/anti-bot variants of pages lacking pageProps; feeding raw JSON arrays where objects are expected.","solutions":["Inspect what the payload actually was (log JSON.stringify of it before asserting)","Retry the fetch — a missing __NEXT_DATA__ is often a transient/interstitial page","Wrap with your own shape check (plain-object guard) and handle the alternate shape explicitly"],"exampleFix":"// before\nassertPlainObject(maybeArray, 'bd payload')\n// after\nif (Array.isArray(maybeArray)) maybeArray = maybeArray[0] ?? {};\nassertPlainObject(maybeArray, 'bd payload')","handlingStrategy":"type-guard","validationCode":"function isPlainObject(v) {\n  return v != null && typeof v === 'object' && !Array.isArray(v);\n}\nif (!isPlainObject(payload)) throw new Error('Unexpected payload shape');","typeGuard":"function isPlainObject(v) {\n  return typeof v === 'object' && v !== null && !Array.isArray(v);\n}","tryCatchPattern":"try {\n  assertPlainObject(payload, 'pageProps');\n} catch (err) {\n  if (err instanceof CommandExecutionError && /unexpected payload shape/.test(err.message)) {\n    console.error('Payload was:', JSON.stringify(payload)?.slice(0, 200));\n  } else throw err;\n}","preventionTips":["Log/log a truncated JSON of payloads before asserting so failures are debuggable","Handle arrays/strings explicitly when an endpoint can return multiple shapes","Retry fetches when __NEXT_DATA__ is missing — often a transient page variant"],"tags":["scraping","schema-validation","data-shape"],"backgroundTag":"unexpected-response-shape","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}