jackwener/OpenCLI · error · CommandExecutionError
Malformed Xiaohongshu user snapshot
Error message
Malformed Xiaohongshu user snapshot
What it means
assertReadableUserSnapshot validates the snapshot object returned by readUserSnapshot (which evaluates USER_SNAPSHOT_JS in the page). If the snapshot is not a plain object (null, undefined, or an array), the function throws this base CommandExecutionError. It means the in-page extraction script returned nothing usable at all — the page state could not even be read.
Source
Thrown at clis/xiaohongshu/user.js:43
const loggedInVal = hasUserStore ? (userStore.loggedIn?._value ?? userStore.loggedIn) : undefined;
const pathName = (typeof location !== 'undefined' && location.pathname) ? location.pathname : '';
const onLoginPage = pathName.indexOf('/login') === 0;
return {
noteGroups: safeClone(rawNotes || []),
pageData: safeClone(rawPageData || {}),
storePresent: hasUserStore,
notesPresent: Array.isArray(rawNotes),
pageDataPresent: Boolean(rawPageData && typeof rawPageData === 'object' && Object.keys(rawPageData).length > 0),
loginWall: Boolean(onLoginPage || loggedInVal === false),
};
})()
`;
async function readUserSnapshot(page) {
return await page.evaluate(USER_SNAPSHOT_JS);
}
export function assertReadableUserSnapshot(snapshot) {
if (!snapshot || typeof snapshot !== 'object' || Array.isArray(snapshot)) {
throw new CommandExecutionError('Malformed Xiaohongshu user snapshot');
}
if (snapshot.storePresent !== true) {
throw new CommandExecutionError('Malformed Xiaohongshu user snapshot: user store was not found');
}
if (snapshot.notesPresent !== true || !Array.isArray(snapshot.noteGroups)) {
throw new CommandExecutionError('Malformed Xiaohongshu user snapshot: notes array was not found');
}
}
/** 展平 noteGroups 后的真实笔记条数。小红书 user store 的 notes 是 [tab[], tab[], ...]
* 形态(每个 tab 一个数组),首屏笔记在其中某个 tab 里;这里数所有 tab 里的笔记总数。 */
export function countFlatNotes(snapshot) {
const groups = snapshot?.noteGroups;
if (!Array.isArray(groups))
return 0;
let n = 0;
for (const g of groups)
n += Array.isArray(g) ? g.length : (g ? 1 : 0);
return n;View on GitHub (pinned to 49907e53dc)
Solutions
- Re-run after waiting for page hydration (user store is injected asynchronously after page.goto)
- Check that the page actually loaded xiaohongshu.com content and not a login/challenge/captcha page
- Log the raw evaluate result before assertion to see what USER_SNAPSHOT_JS actually returned
- Add a hydration wait before readUserSnapshot, as done in note.js/download.js
Example fix
// before
const snapshot = await readUserSnapshot(page);
assertReadableUserSnapshot(snapshot);
// after
await page.wait({ time: 2 });
const snapshot = await readUserSnapshot(page);
assertReadableUserSnapshot(snapshot); Defensive patterns
Strategy: type-guard
Type guard
function isUserSnapshot(s) {
return Boolean(s && typeof s === 'object' && !Array.isArray(s) && s.storePresent === true);
}
// usage
const snapshot = await readUserSnapshot(page);
if (!isUserSnapshot(snapshot)) await page.reload(); // before asserting Try / catch
try {
assertReadableUserSnapshot(snapshot);
} catch (err) {
if (/Malformed Xiaohongshu user snapshot$/.test(err.message)) {
await page.reload(); const snapshot2 = await readUserSnapshot(page); assertReadableUserSnapshot(snapshot2);
} else throw err;
} Prevention
- Log the raw evaluate result when snapshots come back unusable
- Ensure the page finished loading before snapshotting
- Detect login/challenge pages before running the snapshot script
When it happens
Trigger: page.evaluate returned null/undefined because USER_SNAPSHOT_JS crashed or returned nothing; the snapshot serialization failed; or the script returned an array instead of an object.
Common situations: Page navigated away or was blocked before evaluate ran; bot-detection served a challenge page with no app state; the evaluate result was not structured-cloneable and came back null.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Malformed Xiaohongshu user snapshot: user store was not foun
- Malformed Xiaohongshu user snapshot: notes array was not fou
- rednote notifications: ${data.error}${data.detail ? ' (' + d
- Upwork feed state (window.__NUXT__.state.${stateKey}) was no
- xiaohongshu creator-note-detail: signed API ${suffix} return
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/2ce136f9b8cb5fdf.
Report an issue: GitHub.