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 article command reads the x.com CSRF token (ct0 cookie) from the browser session via CDP before making authenticated API calls. If no ct0 cookie exists, it throws AuthRequiredError('x.com'), meaning the browser session is not logged into x.com and API requests would be rejected.
Source
Thrown at clis/twitter/article.js:64
if (m2) return m2[1];
}
return null;
})()
`);
const resolvedTweetId = unwrapBrowserResult(resolvedId);
if (!resolvedTweetId || typeof resolvedTweetId !== 'string') {
throw new CommandExecutionError(`Could not resolve article ${tweetId} to a tweet ID. The article page may not contain a linked tweet.`);
}
tweetId = resolvedTweetId;
}
// Navigate to the tweet page for cookie context
await page.goto(`https://x.com/i/status/${tweetId}`);
await page.wait(3);
// Read CSRF token directly from the cookie store via CDP — zero page.evaluate round-trip
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, 'TweetResultByRestId', TWEET_RESULT_BY_REST_ID_QUERY_ID);
const rawResult = unwrapBrowserResult(await page.evaluate(`
async () => {
const tweetId = ${JSON.stringify(tweetId)};
const ct0 = ${JSON.stringify(ct0)};
const bearer = ${JSON.stringify(TWITTER_BEARER_TOKEN)};
const headers = {
'Authorization': 'Bearer ' + decodeURIComponent(bearer),
'X-Csrf-Token': ct0,
'X-Twitter-Auth-Type': 'OAuth2Session',
'X-Twitter-Active-User': 'yes'
};
const variables = JSON.stringify({
tweetId: tweetId,
withCommunity: false,
includePromotedContent: false,View on GitHub (pinned to 49907e53dc)
Solutions
- Run the twitter login command (or log into x.com in the CLI's browser) before article
- Re-login if your x.com session expired — verify ct0 exists via browser devtools
- Point the command at the profile where you are actually logged in
- Avoid clearing cookies for x.com between runs
Example fix
// before node cli.js twitter article <id> // fresh profile, no login // after node cli.js twitter login node cli.js twitter article <id>
Defensive patterns
Strategy: validation
Validate before calling
// before invoking article, confirm the session has the ct0 cookie
const cookies = await page.getCookies({ url: 'https://x.com' });
if (!cookies.some((c) => c.name === 'ct0')) {
throw new Error('Run `twitter login` first — no x.com session');
} Type guard
function hasCt0Cookie(cookies) { return Array.isArray(cookies) && cookies.some((c) => c.name === 'ct0' && !!c.value); } Try / catch
import { AuthRequiredError } from '@jackwener/opencli/errors';
try {
await articleCmd({ tweetId });
} catch (err) {
if (err instanceof AuthRequiredError) {
console.error('Not logged into x.com — run twitter login and retry');
} else throw err;
} Prevention
- Run twitter login before any authenticated twitter command
- Avoid clearing x.com cookies between runs
- Re-login when sessions expire (401 patterns elsewhere)
- Use a dedicated, persistent browser profile for the CLI
When it happens
Trigger: Running twitter article with a browser profile that has no logged-in x.com session — cookies for https://x.com contain no ct0 entry.
Common situations: Fresh/never-logged-in browser profile, x.com session expired since last login, logging out of x.com manually, running in a CI/headless container with an empty profile, or cookies cleared between runs.
Related errors
- Not logged into x.com (no ct0 cookie)
- Not logged into x.com (no ct0 cookie)
- Not logged into x.com (no ct0 cookie)
- Not logged into x.com (no ct0 cookie)
- Not logged into x.com (no ct0 cookie)
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/62b5e74b48f09e51.
Report an issue: GitHub.