jackwener/OpenCLI · error · CliError
AUTH_REQUIRED
AUTH_REQUIRED
Error message
Douban requires a logged-in browser session before these commands can load data.
What it means
ensureDoubanReady loads a douban page and inspects its state: a sec.douban.com redirect, a login-jump title, or an '异常请求' (abnormal request) body means douban is blocking unauthenticated access. It throws CliError with code AUTH_REQUIRED because all data commands need a logged-in browser session.
Source
Thrown at clis/douban/utils.js:94
if (!match) {
return { title: normalized, originalTitle: '' };
}
return {
title: normalizeText(match[1]),
originalTitle: normalizeText(match[2]),
};
}
async function ensureDoubanReady(page) {
const state = await page.evaluate(`
(() => {
const title = (document.title || '').trim();
const href = (location.href || '').trim();
const blocked = href.includes('sec.douban.com') || /登录跳转/.test(title) || /异常请求/.test(document.body?.innerText || '');
return { blocked, title, href };
})()
`);
if (state?.blocked) {
throw new CliError('AUTH_REQUIRED', 'Douban requires a logged-in browser session before these commands can load data.', 'Please sign in to douban.com in the browser that opencli reuses, then rerun the command.');
}
}
function isDetachedPageError(error) {
const message = error instanceof Error ? error.message : String(error || '');
return /Detached while handling command|Debugger is not attached to the tab|Target closed|No tab with id/i.test(message);
}
async function withDetachedRetry(task, options = {}) {
const attempts = Math.max(1, options.attempts || 2);
let lastError;
for (let attempt = 0; attempt < attempts; attempt += 1) {
try {
return await task();
}
catch (error) {
lastError = error;
if (attempt >= attempts - 1 || !isDetachedPageError(error)) {
throw error;
}View on GitHub (pinned to 49907e53dc)
Solutions
- Sign in to douban.com in the browser profile opencli reuses, then rerun the command
- Run the douban site-auth/login command to open the login page and authenticate
- If blocked at sec.douban.com despite login, solve the challenge manually in the browser and retry after a pause
Defensive patterns
Strategy: try-catch
Validate before calling
await page.goto('https://www.douban.com/mine/');
const authed = !page.url().includes('sec.douban.com') && !page.url().includes('accounts.douban.com');
if (!authed) console.error('Log in to douban.com in the reused browser before running data commands'); Type guard
function doubanBlockedState(state) { return state && state.blocked === true; } Try / catch
try { await doubanData(cmd, args); } catch (e) { if (e.code === 'AUTH_REQUIRED') { await openDoubanLoginAndWait(); return doubanData(cmd, args); } throw e; } Prevention
- Log in once manually in the reused profile before automation
- Detect sec.douban.com redirects and pause instead of hammering (anti-bot)
- Check for a valid session at job start, not mid-run
When it happens
Trigger: Hitting douban data endpoints (subject pages, book/movie hot lists) from an anonymous browser profile; douban risk-control redirecting to sec.douban.com; a previously valid session fully expired.
Common situations: First run on a new machine/profile; headless automation without prior manual login; heavy scraping triggering douban's anti-bot gate even for previously valid sessions.
Related errors
- Douban dbcl2 / ck cookies missing
- ${probe.detail}
- [taxonomy=selector_drift] site=powerchina command=search log
- xueqiu.com
- 请先在共享 Chrome 完成 1688 登录/验证,再重试(${action})
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/e2522e547e004af6.
Report an issue: GitHub.