{"record":{"id":"16696dfac4e0639c","repo":"jackwener/OpenCLI","slug":"could-not-detect-logged-in-user-are-you-logged-in","errorCode":null,"errorMessage":"Could not detect logged-in user. Are you logged in?","messagePattern":"Could not detect logged-in user\\. Are you logged in\\?","errorType":"exception","errorClass":"AuthRequiredError","httpStatus":null,"severity":"error","filePath":"clis/twitter/user-timeline.js","lineNumber":180,"sourceCode":"        throw new ArgumentError(\n            `twitter ${commandName} username must be a valid Twitter/X handle`,\n            commandName === 'collection'\n                ? 'Example: opencli twitter collection @jack --until 2026-07-23T00:00:00Z'\n                : 'Example: opencli twitter tweets @jack --limit 20',\n        );\n    }\n    if (!username && !allowLoggedInDefault) {\n        throw new ArgumentError('twitter collection username must be a valid Twitter/X handle', 'Example: opencli twitter collection @jack --until 2026-07-23T00:00:00Z');\n    }\n    if (!username) {\n        await page.goto('https://x.com/home');\n        await page.wait({ selector: '[data-testid=\"primaryColumn\"]' });\n        const href = unwrapBrowserResult(await page.evaluate(`() => {\n            const link = document.querySelector('a[data-testid=\"AppTabBar_Profile_Link\"]');\n            return link ? link.getAttribute('href') : null;\n        }`));\n        if (!href || typeof href !== 'string') {\n            throw new AuthRequiredError('x.com', 'Could not detect logged-in user. Are you logged in?');\n        }\n        username = normalizeTwitterScreenName(href);\n        if (!username) {\n            throw new AuthRequiredError('x.com', 'Could not detect logged-in user. Are you logged in?');\n        }\n    }\n\n    const cookies = await page.getCookies({ url: 'https://x.com' });\n    const ct0 = cookies.find((cookie) => cookie.name === 'ct0')?.value || null;\n    if (!ct0) throw new AuthRequiredError('x.com', 'Not logged into x.com (no ct0 cookie)');\n\n    const userTweetsOperation = await resolveTwitterOperationMetadata(page, 'UserTweets', USER_TWEETS_OPERATION);\n    const userByScreenNameOperation = await resolveTwitterOperationMetadata(page, 'UserByScreenName', USER_BY_SCREEN_NAME_OPERATION);\n    const headers = JSON.stringify({\n        Authorization: `Bearer ${decodeURIComponent(TWITTER_BEARER_TOKEN)}`,\n        'X-Csrf-Token': ct0,\n        'X-Twitter-Auth-Type': 'OAuth2Session',\n        'X-Twitter-Active-User': 'yes',","sourceCodeStart":162,"sourceCodeEnd":198,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/twitter/user-timeline.js#L162-L198","documentation":"When no username was given and the logged-in default is allowed, the helper navigates to x.com/home and reads the profile link `a[data-testid=\"AppTabBar_Profile_Link\"]` to detect the current user. If the link is absent/not a string, or its href does not normalize to a valid handle, it throws this AuthRequiredError for x.com. The library cannot determine who is logged in, which almost always means there is no usable authenticated session.","triggerScenarios":"Calling `twitter tweets`/`collection` without a username while the x.com session is logged out, expired, or showing a logged-out home layout without the AppTabBar profile link; the page renders but the href is null or unparseable.","commonSituations":"ct0/auth_token cookies expired; login wall or NOSCRIPT interstitial replacing the home DOM; X.com A/B test renaming the AppTabBar_Profile_Link testid; automation-detected logged-out state.","solutions":["Log into x.com in the opencli browser session (`opencli browser login x.com` or manual login), then re-run without the username or pass one explicitly.","Simplest workaround: pass the username explicitly (`opencli twitter tweets @jack`) so the logged-in detection path is skipped entirely.","Verify the session by opening https://x.com/home in the managed browser and confirming the sidebar profile link exists.","Clear stale cookies and re-login if the session is half-expired; check for X.com DOM testid changes if logged in but still failing."],"exampleFix":"// before\nopencli twitter tweets --limit 20        // no username, session expired -> AuthRequiredError\n// after\nopencli browser login x.com\nopencli twitter tweets --limit 20        // or: opencli twitter tweets @me-handle --limit 20","handlingStrategy":"fallback","validationCode":"// pre-check session before omitting the username\nconst loggedIn = await page.evaluate(`!!document.querySelector('[data-testid=\"AppTabBar_Profile_Link\"]')`);\nif (!loggedIn) {\n  console.log('No logged-in x.com session; pass the username explicitly');\n}","typeGuard":"function hasLoggedInSession(page) {\n  return page !== null && typeof page.evaluate === 'function';\n  // combined with runtime probe: await page.evaluate(`!!document.querySelector('a[data-testid=\"AppTabBar_Profile_Link\"]')`)\n}","tryCatchPattern":"try {\n  await cli.run(['twitter', 'tweets', '--limit', '20']);\n} catch (e) {\n  if (e instanceof AuthRequiredError || /Could not detect logged-in user/.test(e.message)) {\n    await ensureXLogin();\n    await cli.run(['twitter', 'tweets', '--limit', '20']);\n    // or fallback: cli.run(['twitter', 'tweets', explicitHandle, '--limit', '20'])\n  } else throw e;\n}","preventionTips":["Keep the x.com session fresh; re-login when cookies expire.","Pass the username explicitly in scripts/CI instead of relying on logged-in detection.","Periodically open x.com/home in the managed browser to validate the session.","Track X.com testid changes (AppTabBar_Profile_Link) after site updates."],"tags":["authentication","twitter","session","logged-in-detection"],"backgroundTag":"auth-required","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}