{"record":{"id":"7357540ac472bedb","repo":"jackwener/OpenCLI","slug":"webhost-feed-unexpected-items-payload-shape","errorCode":null,"errorMessage":"${webHost} feed: unexpected items payload shape","messagePattern":"(.+?) feed: unexpected items payload shape","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/xiaohongshu/feed.js","lineNumber":111,"sourceCode":"/**\n * Shared func-mode implementation. Exported so the rednote adapter can run the\n * same store read against www.rednote.com without duplicating the logic.\n */\nexport async function runFeed(page, kwargs, webHost) {\n    const limit = parseLimit(kwargs.limit);\n    await page.goto(`https://${webHost}/explore`);\n    // Pinia store hydrates from SSR; give the page a beat to finish\n    // bootstrapping before reading the array.\n    await page.wait({ time: 2 });\n    const data = unwrapEvaluateResult(await page.evaluate(FEEDS_READ_JS));\n    if (!data || typeof data !== 'object') {\n        throw new CommandExecutionError(`${webHost} feed: unexpected evaluate response`);\n    }\n    if (data.error) {\n        throw new CommandExecutionError(`${webHost} feed: ${data.error}`, `The SPA may still be hydrating; reload ${webHost}/explore and retry.`);\n    }\n    if (!Array.isArray(data.items)) {\n        throw new CommandExecutionError(`${webHost} feed: unexpected items payload shape`);\n    }\n    const rows = [];\n    for (const row of data.items) {\n        if (rows.length >= limit)\n            break;\n        if (!row || typeof row !== 'object') {\n            throw new CommandExecutionError(`${webHost} feed: malformed feed item`);\n        }\n        const id = toCleanString(row.id);\n        if (!id) {\n            throw new CommandExecutionError(`${webHost} feed: feed item is missing note id`);\n        }\n        const xsecToken = toCleanString(row.xsecToken);\n        if (!xsecToken) {\n            throw new CommandExecutionError(`${webHost} feed: feed item ${id} is missing xsecToken; cannot build a signed drill-down URL`);\n        }\n        rows.push({\n            id,","sourceCodeStart":93,"sourceCodeEnd":129,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/xiaohongshu/feed.js#L93-L129","documentation":"runFeed requires data.items to be an array. If the hydrated object exists but items is missing or not an array, it throws CommandExecutionError 'unexpected items payload shape'. This validates the feed store schema the CLI depends on.","triggerScenarios":"page.evaluate(FEEDS_READ_JS) returns an object without an items array, e.g. items is undefined, an object map, or a wrapped { list: [...] } structure after a site update.","commonSituations":"Xiaohongshu changed their Pinia store shape (renamed/moved items), explore page rendered an empty/error state whose store lacks items, custom feed types with different payloads.","solutions":["Inspect the store in DevTools to confirm the current items property name/path","Update FEEDS_READ_JS to read the new store path","Retry when the page has fully hydrated so items is populated","Fall back to another feed/tab if the explore feed shape differs"],"exampleFix":"// before (in-page script)\nreturn { items: store.feed.notes };\n// after (tolerate alternate shapes)\nconst raw = store.feed?.notes ?? store.feed?.items ?? [];\nreturn { items: Array.isArray(raw) ? raw : [] };","handlingStrategy":"type-guard","validationCode":"const data = unwrapEvaluateResult(await page.evaluate(FEEDS_READ_JS));\nif (!data || !Array.isArray(data.items)) throw new Error('feed items payload malformed');","typeGuard":"function hasFeedItems(d) { return !!d && typeof d === 'object' && Array.isArray(d.items); }","tryCatchPattern":"try {\n  const rows = await runFeed(page, webHost, limit);\n} catch (err) {\n  if (err instanceof CommandExecutionError && err.message.includes('unexpected items payload shape')) {\n    // inspect raw store in DevTools; update FEEDS_READ_JS to the new items path\n  } else throw err;\n}","preventionTips":["Smoke-test FEEDS_READ_JS in DevTools after site deploys","Normalize alternate item shapes (list/items/notes) inside the in-page script","Wait for full hydration before reading the store"],"tags":["browser-automation","schema","feed"],"backgroundTag":"payload-schema-mismatch","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}