{"record":{"id":"e2522e547e004af6","repo":"jackwener/OpenCLI","slug":"auth-required","errorCode":"AUTH_REQUIRED","errorMessage":"Douban requires a logged-in browser session before these commands can load data.","messagePattern":"Douban requires a logged-in browser session before these commands can load data\\.","errorType":"error_code","errorClass":"CliError","httpStatus":null,"severity":"error","filePath":"clis/douban/utils.js","lineNumber":94,"sourceCode":"    if (!match) {\n        return { title: normalized, originalTitle: '' };\n    }\n    return {\n        title: normalizeText(match[1]),\n        originalTitle: normalizeText(match[2]),\n    };\n}\nasync function ensureDoubanReady(page) {\n    const state = await page.evaluate(`\n    (() => {\n      const title = (document.title || '').trim();\n      const href = (location.href || '').trim();\n      const blocked = href.includes('sec.douban.com') || /登录跳转/.test(title) || /异常请求/.test(document.body?.innerText || '');\n      return { blocked, title, href };\n    })()\n  `);\n    if (state?.blocked) {\n        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.');\n    }\n}\nfunction isDetachedPageError(error) {\n    const message = error instanceof Error ? error.message : String(error || '');\n    return /Detached while handling command|Debugger is not attached to the tab|Target closed|No tab with id/i.test(message);\n}\nasync function withDetachedRetry(task, options = {}) {\n    const attempts = Math.max(1, options.attempts || 2);\n    let lastError;\n    for (let attempt = 0; attempt < attempts; attempt += 1) {\n        try {\n            return await task();\n        }\n        catch (error) {\n            lastError = error;\n            if (attempt >= attempts - 1 || !isDetachedPageError(error)) {\n                throw error;\n            }","sourceCodeStart":76,"sourceCodeEnd":112,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/douban/utils.js#L76-L112","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"await page.goto('https://www.douban.com/mine/');\nconst authed = !page.url().includes('sec.douban.com') && !page.url().includes('accounts.douban.com');\nif (!authed) console.error('Log in to douban.com in the reused browser before running data commands');","typeGuard":"function doubanBlockedState(state) { return state && state.blocked === true; }","tryCatchPattern":"try { await doubanData(cmd, args); } catch (e) { if (e.code === 'AUTH_REQUIRED') { await openDoubanLoginAndWait(); return doubanData(cmd, args); } throw e; }","preventionTips":["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"],"tags":["auth","douban","login-required","anti-bot","cli-error"],"backgroundTag":"auth-required-login-first","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}