jackwener/OpenCLI · error · AuthRequiredError
Not logged into x.com (no ct0 cookie)
Error message
Not logged into x.com (no ct0 cookie)
What it means
The bookmarks fetch authenticates using the browser session's ct0 CSRF cookie from x.com. clis/twitter/bookmarks.js:207 throws AuthRequiredError('x.com', ...) when page.getCookies() finds no ct0 cookie, meaning the browser page is not logged into x.com. Without ct0 the GraphQL request would be rejected, so the CLI fails fast.
Source
Thrown at clis/twitter/bookmarks.js:207
const useOutputFile = Boolean(fetchAll && outputFile);
const maxPages = resolveMaxPages(kwargs, fetchAll);
const topByEngagement = Number(kwargs['top-by-engagement'] || 0);
if (useOutputFile && topByEngagement > 0) {
throw new ArgumentError('--top-by-engagement cannot be combined with --output-file');
}
if (outputFile && !fetchAll) {
throw new ArgumentError('--output-file requires --all');
}
if (resumeFile && !fetchAll) {
throw new ArgumentError('--resume-file requires --all');
}
if (outputFile && !resumeFile) {
throw new ArgumentError('--output-file requires --resume-file so partial archives remain resumable');
}
const cookies = await page.getCookies({ url: 'https://x.com' });
const ct0 = cookies.find((c) => c.name === 'ct0')?.value || null;
if (!ct0)
throw new AuthRequiredError('x.com', 'Not logged into x.com (no ct0 cookie)');
const queryId = await resolveTwitterQueryId(page, 'Bookmarks', BOOKMARKS_QUERY_ID);
const headers = JSON.stringify({
'Authorization': `Bearer ${decodeURIComponent(TWITTER_BEARER_TOKEN)}`,
'X-Csrf-Token': ct0,
'X-Twitter-Auth-Type': 'OAuth2Session',
'X-Twitter-Active-User': 'yes',
});
const resumed = fetchAll ? readResumeFile(resumeFile, {
source: 'bookmarks',
outputFile: useOutputFile ? outputFile : null,
}) : null;
if (useOutputFile && resumed && resumed.count > 0 && !fs.existsSync(outputFile)) {
throw new CommandExecutionError(`Twitter bookmarks output file is missing for resume state: ${outputFile}`);
}
if (useOutputFile && !resumed && fs.existsSync(outputFile)) {
throw new ArgumentError(`Refusing to overwrite existing Twitter bookmarks output file: ${outputFile}`);
}
const allTweets = useOutputFile ? [] : (resumed?.tweets ? [...resumed.tweets] : []);View on GitHub (pinned to 49907e53dc)
Solutions
- Log into x.com in the browser/profile the CLI drives, then re-run the command.
- Verify the ct0 cookie exists: page.getCookies({ url: 'https://x.com' }) should include a cookie named 'ct0'.
- Use a persistent browser profile (not incognito) so the session survives restarts.
- Re-authenticate if the session expired, then retry.
Example fix
// before: fresh context with no login
const context = await browser.newContext();
// after: use the logged-in persistent profile
const context = await browser.newContext({ storageState: 'x-auth.json' }); Defensive patterns
Strategy: validation
Validate before calling
const cookies = await page.getCookies({ url: 'https://x.com' });
if (!cookies.some((c) => c.name === 'ct0')) {
throw new Error('Not logged into x.com (no ct0 cookie) — login before running');
} Type guard
function hasCt0Cookie(cookies) {
return Array.isArray(cookies) && cookies.some((c) => c && c.name === 'ct0' && typeof c.value === 'string' && c.value.length > 0);
} Try / catch
try {
await runBookmarks(argv);
} catch (e) {
if (e instanceof AuthRequiredError) {
console.error(`Login required for ${e.domain ?? 'x.com'}: ${e.message}. Open the browser profile and log in, then retry.`);
process.exitCode = 1;
} else throw e;
} Prevention
- Use a persistent browser profile with a valid x.com session, not incognito.
- Check for the ct0 cookie as a preflight step before any x.com automation.
- Re-login proactively when sessions age out; monitor auth failures in logs.
- Save/restore storageState so sessions survive browser restarts.
When it happens
Trigger: The automated browser page's cookie jar for https://x.com contains no cookie named ct0 — i.e. the page is logged out or the session was never established — detected right after `page.getCookies({ url: 'https://x.com' })`.
Common situations: Expired or revoked x.com login in the automation browser profile; running against a fresh/incognito browser context; corporate proxy or cookie clearing wiping session cookies; login flow changed and ct0 not yet set before the CLI reads cookies.
Related errors
- Bilibili ${label} API requires login or permission: ${messag
- bilibili.com
- result.detail (auth required from Claude probe)
- auth
- quark.cn
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/e74f56367168ffed.
Report an issue: GitHub.