{"record":{"id":"62b5e74b48f09e51","repo":"jackwener/OpenCLI","slug":"not-logged-into-x-com-no-ct0-cookie","errorCode":null,"errorMessage":"Not logged into x.com (no ct0 cookie)","messagePattern":"Not logged into x\\.com \\(no ct0 cookie\\)","errorType":"exception","errorClass":"AuthRequiredError","httpStatus":null,"severity":"error","filePath":"clis/twitter/article.js","lineNumber":64,"sourceCode":"            if (m2) return m2[1];\n          }\n          return null;\n        })()\n      `);\n            const resolvedTweetId = unwrapBrowserResult(resolvedId);\n            if (!resolvedTweetId || typeof resolvedTweetId !== 'string') {\n                throw new CommandExecutionError(`Could not resolve article ${tweetId} to a tweet ID. The article page may not contain a linked tweet.`);\n            }\n            tweetId = resolvedTweetId;\n        }\n        // Navigate to the tweet page for cookie context\n        await page.goto(`https://x.com/i/status/${tweetId}`);\n        await page.wait(3);\n        // Read CSRF token directly from the cookie store via CDP — zero page.evaluate round-trip\n        const cookies = await page.getCookies({ url: 'https://x.com' });\n        const ct0 = cookies.find((c) => c.name === 'ct0')?.value || null;\n        if (!ct0)\n            throw new AuthRequiredError('x.com', 'Not logged into x.com (no ct0 cookie)');\n        const queryId = await resolveTwitterQueryId(page, 'TweetResultByRestId', TWEET_RESULT_BY_REST_ID_QUERY_ID);\n        const rawResult = unwrapBrowserResult(await page.evaluate(`\n      async () => {\n        const tweetId = ${JSON.stringify(tweetId)};\n        const ct0 = ${JSON.stringify(ct0)};\n\n        const bearer = ${JSON.stringify(TWITTER_BEARER_TOKEN)};\n        const headers = {\n          'Authorization': 'Bearer ' + decodeURIComponent(bearer),\n          'X-Csrf-Token': ct0,\n          'X-Twitter-Auth-Type': 'OAuth2Session',\n          'X-Twitter-Active-User': 'yes'\n        };\n\n        const variables = JSON.stringify({\n          tweetId: tweetId,\n          withCommunity: false,\n          includePromotedContent: false,","sourceCodeStart":46,"sourceCodeEnd":82,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/twitter/article.js#L46-L82","documentation":"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.","triggerScenarios":"Running twitter article with a browser profile that has no logged-in x.com session — cookies for https://x.com contain no ct0 entry.","commonSituations":"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.","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"],"exampleFix":"// before\nnode cli.js twitter article <id>   // fresh profile, no login\n// after\nnode cli.js twitter login\nnode cli.js twitter article <id>","handlingStrategy":"validation","validationCode":"// before invoking article, confirm the session has the ct0 cookie\nconst cookies = await page.getCookies({ url: 'https://x.com' });\nif (!cookies.some((c) => c.name === 'ct0')) {\n  throw new Error('Run `twitter login` first — no x.com session');\n}","typeGuard":"function hasCt0Cookie(cookies) { return Array.isArray(cookies) && cookies.some((c) => c.name === 'ct0' && !!c.value); }","tryCatchPattern":"import { AuthRequiredError } from '@jackwener/opencli/errors';\ntry {\n  await articleCmd({ tweetId });\n} catch (err) {\n  if (err instanceof AuthRequiredError) {\n    console.error('Not logged into x.com — run twitter login and retry');\n  } else throw err;\n}","preventionTips":["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"],"tags":["auth","cookies","twitter"],"backgroundTag":"missing-auth-cookie","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}