jackwener/OpenCLI · error · CommandExecutionError
Malformed Xiaohongshu user snapshot: user store was not foun
Error message
Malformed Xiaohongshu user snapshot: user store was not found
What it means
The snapshot came back as an object but its storePresent flag was not true, meaning USER_SNAPSHOT_JS could not find the user store (e.g. __INITIAL_STATE__.user) on the page. This is a known hydration race: the store is injected asynchronously by SSR/client bootstrap after page.goto, so evaluating too early intermittently fails (documented in the source as the 2026-06-09 bug fixed by adding page.wait).
Source
Thrown at clis/xiaohongshu/user.js:46
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;
}
/** 页面是否被登录墙挡(302 到 /login,或 user store loggedIn=false)。 */
export function isLoginWallSnapshot(snapshot) {View on GitHub (pinned to 49907e53dc)
Solutions
- Retry the command — the comment in user.js says hydration waits + retries were added precisely for this intermittent race
- Wait for the store before evaluating (waitForSelector or wait-for-function on __INITIAL_STATE__.user)
- Check for a login wall: if the page redirected to /login the store will never appear — re-authenticate instead of retrying
- Slow network: increase the hydration wait duration
Example fix
// before
const snapshot = await readUserSnapshot(page);
// after
await page.waitForFunction(() => window.__INITIAL_STATE__?.user, { timeout: 15000 });
const snapshot = await readUserSnapshot(page); Defensive patterns
Strategy: retry
Validate before calling
await page.waitForFunction(() => Boolean(window.__INITIAL_STATE__?.user), { timeout: 15000 }); Type guard
function hasUserStore(s) { return Boolean(s && typeof s === 'object' && s.storePresent === true); } Try / catch
try {
await getUserProfile(url);
} catch (err) {
if (/user store was not found/.test(err.message)) {
await sleep(3000); await retryWithBackoff(() => getUserProfile(url), 3);
} else throw err;
} Prevention
- Always wait for __INITIAL_STATE__.user before evaluate (the documented hydration race fix)
- Use retries with backoff for first-load scenarios on slow networks
- Distinguish login-wall (use AuthRequiredError path) from hydration failure before retrying
When it happens
Trigger: Evaluating USER_SNAPSHOT_JS immediately after page.goto before the client bootstrap injects __INITIAL_STATE__.user; landing on a page variant without the user store; login-walled or error page lacking app state.
Common situations: Slow network/CPU on first load; cold page with no cache; fetching a user profile right after navigation in a fresh browser context.
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
- Gmail ${operation} could not find the search input
- composer fill was not verified
- rednote notifications: ${data.error}${data.detail ? ' (' + d
- Upwork feed state (window.__NUXT__.state.${stateKey}) was no
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/297c6d1ca908ebab.
Report an issue: GitHub.