jackwener/OpenCLI · error · AuthRequiredError

Xiaohongshu profile requires login (page redirected to /logi

Error message

Xiaohongshu profile requires login (page redirected to /login or session expired); re-login to xiaohongshu.com and retry.

What it means

The profile page hit a login wall: the snapshot's loginWall flag was true (page redirected to /login or the user store reported loggedIn=false), so throwLoginWallAuthRequired throws AuthRequiredError for xiaohongshu.com. The library treats this as an authentication problem, not a fetch failure — the session cookie is expired or missing.

Source

Thrown at clis/xiaohongshu/user.js:68

    }
}
/** 展平 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) {
    return Boolean(snapshot && typeof snapshot === 'object' && snapshot.loginWall === true);
}
function throwLoginWallAuthRequired() {
    throw new AuthRequiredError('xiaohongshu.com', 'Xiaohongshu profile requires login (page redirected to /login or session expired); re-login to xiaohongshu.com and retry.');
}
/**
 * 读取 user 快照,带 hydration 等待 + 重试。修两个真实坑:
 *  1) 慢加载竞态:`__INITIAL_STATE__.user` 由 SSR/client bootstrap 异步注入,`page.goto` 后
 *     立刻 evaluate 会撞 hydration 窗口 → store/notes 尚未就绪。note.js / download.js 早用
 *     `page.wait` 规避,唯独 user.js 漏了 → 间歇性 "user store was not found"(2026-06-09 整批
 *     seed 全挂、2026-05-20 亦复现)。
 *  2) 笔记懒加载:`notes` 是 [tab[], ...] 形态,首屏笔记可能比 store 更晚填充。
 * 策略:先快读一次(页面已就绪则零额外延迟,保住快加载路径);未拿到笔记**且非登录墙**就
 * `page.wait` 后重试至多 maxRetries 次。命中登录墙立即停(再等无用,交给 caller 抛 AUTH_REQUIRED);
 * 真·空号(销号/私密/全删)走满重试后返回空快照,由下游 EmptyResultError 正确收尾。导出供测试。
 */
export async function readUserSnapshotHydrated(page, maxRetries = 8, waitSeconds = 2) {
    let snapshot = await readUserSnapshot(page);
    for (let i = 0; i < maxRetries && !isLoginWallSnapshot(snapshot) && countFlatNotes(snapshot) === 0; i += 1) {
        await page.wait({ time: waitSeconds });
        snapshot = await readUserSnapshot(page);
    }

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Re-login to xiaohongshu.com in the browser context used by the CLI (refresh cookies), then retry the command
  2. Use the library's auth/login flow for xiaohongshu if available to refresh credentials
  3. Verify cookies persist across runs (same user-data-dir) instead of a fresh context each time
  4. Check the target profile in a normal browser to confirm it isn't actually a public redirect to /login
Defensive patterns

Strategy: try-catch

Try / catch

import { AuthRequiredError } from '...';
try {
  await getUserProfile(url);
} catch (err) {
  if (err instanceof AuthRequiredError) {
    await reloginXiaohongshu(); // refresh cookies, then retry once
    return getUserProfile(url);
  }
  throw err;
}

Prevention

When it happens

Trigger: Session cookies expired since last login; the profile fetch triggered a 302 to /login; the page's user store explicitly reports loggedIn=false; cookies were cleared or the browser profile was reset.

Common situations: Long-running automation whose xiaohongshu session aged out; running on a machine/browser context that was never logged in; site forcing re-login due to suspicious activity.

Related errors


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/6280183211c7a0e7. Report an issue: GitHub.