jackwener/OpenCLI · error · AuthRequiredError
Could not detect logged-in user. Are you logged in?
Error message
Could not detect logged-in user. Are you logged in?
What it means
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.
Source
Thrown at clis/twitter/user-timeline.js:180
throw new ArgumentError(
`twitter ${commandName} username must be a valid Twitter/X handle`,
commandName === 'collection'
? 'Example: opencli twitter collection @jack --until 2026-07-23T00:00:00Z'
: 'Example: opencli twitter tweets @jack --limit 20',
);
}
if (!username && !allowLoggedInDefault) {
throw new ArgumentError('twitter collection username must be a valid Twitter/X handle', 'Example: opencli twitter collection @jack --until 2026-07-23T00:00:00Z');
}
if (!username) {
await page.goto('https://x.com/home');
await page.wait({ selector: '[data-testid="primaryColumn"]' });
const href = unwrapBrowserResult(await page.evaluate(`() => {
const link = document.querySelector('a[data-testid="AppTabBar_Profile_Link"]');
return link ? link.getAttribute('href') : null;
}`));
if (!href || typeof href !== 'string') {
throw new AuthRequiredError('x.com', 'Could not detect logged-in user. Are you logged in?');
}
username = normalizeTwitterScreenName(href);
if (!username) {
throw new AuthRequiredError('x.com', 'Could not detect logged-in user. Are you logged in?');
}
}
const cookies = await page.getCookies({ url: 'https://x.com' });
const ct0 = cookies.find((cookie) => cookie.name === 'ct0')?.value || null;
if (!ct0) throw new AuthRequiredError('x.com', 'Not logged into x.com (no ct0 cookie)');
const userTweetsOperation = await resolveTwitterOperationMetadata(page, 'UserTweets', USER_TWEETS_OPERATION);
const userByScreenNameOperation = await resolveTwitterOperationMetadata(page, 'UserByScreenName', USER_BY_SCREEN_NAME_OPERATION);
const headers = JSON.stringify({
Authorization: `Bearer ${decodeURIComponent(TWITTER_BEARER_TOKEN)}`,
'X-Csrf-Token': ct0,
'X-Twitter-Auth-Type': 'OAuth2Session',
'X-Twitter-Active-User': 'yes',View on GitHub (pinned to 49907e53dc)
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.
Example fix
// before opencli twitter tweets --limit 20 // no username, session expired -> AuthRequiredError // after opencli browser login x.com opencli twitter tweets --limit 20 // or: opencli twitter tweets @me-handle --limit 20
Defensive patterns
Strategy: fallback
Validate before calling
// pre-check session before omitting the username
const loggedIn = await page.evaluate(`!!document.querySelector('[data-testid="AppTabBar_Profile_Link"]')`);
if (!loggedIn) {
console.log('No logged-in x.com session; pass the username explicitly');
} Type guard
function hasLoggedInSession(page) {
return page !== null && typeof page.evaluate === 'function';
// combined with runtime probe: await page.evaluate(`!!document.querySelector('a[data-testid="AppTabBar_Profile_Link"]')`)
} Try / catch
try {
await cli.run(['twitter', 'tweets', '--limit', '20']);
} catch (e) {
if (e instanceof AuthRequiredError || /Could not detect logged-in user/.test(e.message)) {
await ensureXLogin();
await cli.run(['twitter', 'tweets', '--limit', '20']);
// or fallback: cli.run(['twitter', 'tweets', explicitHandle, '--limit', '20'])
} else throw e;
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Not logged into x.com (no ct0 cookie)
- 12306 tk auth cookie missing
- Band band_session cookie missing
- ${probe.detail}
- Browser session required for bilibili follow
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/16696dfac4e0639c.
Report an issue: GitHub.