{"record":{"id":"7b644011e59e96b2","repo":"jackwener/OpenCLI","slug":"malformed-xiaohongshu-user-snapshot-notes-array-w","errorCode":null,"errorMessage":"Malformed Xiaohongshu user snapshot: notes array was not found","messagePattern":"Malformed Xiaohongshu user snapshot: notes array was not found","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/xiaohongshu/user.js","lineNumber":49,"sourceCode":"        storePresent: hasUserStore,\n        notesPresent: Array.isArray(rawNotes),\n        pageDataPresent: Boolean(rawPageData && typeof rawPageData === 'object' && Object.keys(rawPageData).length > 0),\n        loginWall: Boolean(onLoginPage || loggedInVal === false),\n      };\n    })()\n  `;\nasync function readUserSnapshot(page) {\n    return await page.evaluate(USER_SNAPSHOT_JS);\n}\nexport function assertReadableUserSnapshot(snapshot) {\n    if (!snapshot || typeof snapshot !== 'object' || Array.isArray(snapshot)) {\n        throw new CommandExecutionError('Malformed Xiaohongshu user snapshot');\n    }\n    if (snapshot.storePresent !== true) {\n        throw new CommandExecutionError('Malformed Xiaohongshu user snapshot: user store was not found');\n    }\n    if (snapshot.notesPresent !== true || !Array.isArray(snapshot.noteGroups)) {\n        throw new CommandExecutionError('Malformed Xiaohongshu user snapshot: notes array was not found');\n    }\n}\n/** 展平 noteGroups 后的真实笔记条数。小红书 user store 的 notes 是 [tab[], tab[], ...]\n *  形态（每个 tab 一个数组），首屏笔记在其中某个 tab 里；这里数所有 tab 里的笔记总数。 */\nexport function countFlatNotes(snapshot) {\n    const groups = snapshot?.noteGroups;\n    if (!Array.isArray(groups))\n        return 0;\n    let n = 0;\n    for (const g of groups)\n        n += Array.isArray(g) ? g.length : (g ? 1 : 0);\n    return n;\n}\n/** 页面是否被登录墙挡（302 到 /login，或 user store loggedIn=false）。 */\nexport function isLoginWallSnapshot(snapshot) {\n    return Boolean(snapshot && typeof snapshot === 'object' && snapshot.loginWall === true);\n}\nfunction throwLoginWallAuthRequired() {","sourceCodeStart":31,"sourceCodeEnd":67,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/xiaohongshu/user.js#L31-L67","documentation":"The snapshot had a readable user store but its notes data was missing: notesPresent was not true or noteGroups was not an array. The xiaohongshu user store keeps notes as [tab[], tab[], ...] groups; if that structure is absent the profile's note data never loaded. Downstream note-count/scroll logic depends on it.","triggerScenarios":"The notes arrays had not hydrated yet when the snapshot was taken; the user profile page variant renders notes differently (e.g. empty state, suspended account); site changed the store shape so notesPresent check no longer matches.","commonSituations":"Profiles whose notes lazy-load only after scrolling; users with zero public notes; site-side schema update renaming the notes field.","solutions":["Retry — notes may just be slow to hydrate; wait for the notes group to appear before snapshotting","Check whether the profile genuinely has no public notes (in which case the command will next throw EmptyResultError)","Inspect the live store shape in devtools and update USER_SNAPSHOT_JS/notesPresent detection after site schema changes","Try a different profile to distinguish per-user empty state from a broken selector"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"await page.waitForFunction(() => Array.isArray(window.__INITIAL_STATE__?.user?.notes), { timeout: 15000 });","typeGuard":"function hasNotes(s) { return Boolean(s && typeof s === 'object' && s.notesPresent === true && Array.isArray(s.noteGroups)); }","tryCatchPattern":"try {\n  await getUserProfile(url);\n} catch (err) {\n  if (/notes array was not found/.test(err.message)) {\n    await sleep(3000); await retryWithBackoff(() => getUserProfile(url), 2);\n  } else throw err;\n}","preventionTips":["Wait for the notes arrays to hydrate before snapshotting","Remember profiles can legitimately have zero notes (leads to EMPTY_RESULT, not this error)","Re-validate store schema assumptions after site updates"],"tags":["hydration","snapshot","schema-change","xiaohongshu"],"backgroundTag":"malformed-page-snapshot","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}