jackwener/OpenCLI · error · AuthRequiredError

Could not find logged-in user profile link. Are you logged i

Error message

Could not find logged-in user profile link. Are you logged in?

What it means

When no user argument is supplied the command resolves the logged-in account by reading the href of the AppTabBar_Profile_Link element on x.com/home. If the selector returns null or a non-string (e.g. X renamed the testid, or the DOM differs), it cannot determine whose followers to fetch and throws AuthRequiredError. The second message variant means the page is likely not a logged-in home view.

Source

Thrown at clis/twitter/followers.js:120

            throw new ArgumentError('twitter followers user must be a valid Twitter/X handle', 'Example: opencli twitter followers @elonmusk --limit 100');
        }
        await page.goto('https://x.com/home');
        await page.wait({ selector: '[data-testid="primaryColumn"]' });
        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)');
        }

        if (!targetUser) {
            // Bridge wraps primitive page.evaluate returns as { session, data:<value> };
            // unwrap so the href string is usable downstream.
            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 find logged-in user profile link. Are you logged in?');
            }
            targetUser = normalizeScreenName(href);
            if (!targetUser) {
                throw new AuthRequiredError('x.com', 'Could not find logged-in user profile link. Are you logged in?');
            }
        }
        if (!targetUser) {
            throw new ArgumentError('twitter followers user cannot be empty', 'Example: opencli twitter followers @elonmusk --limit 100');
        }

        await page.installInterceptor('/Followers?');
        const targetPath = `/${targetUser}/followers`;
        await page.evaluate(`() => {
            const targetPath = ${JSON.stringify(targetPath)};
            window.history.pushState({}, '', targetPath);
            window.dispatchEvent(new PopStateEvent('popstate', { state: {} }));
        }`);
        try {

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Log into x.com in the tool's browser profile and confirm the profile avatar appears on home
  2. Pass the target handle explicitly (opencli twitter followers @handle) to bypass profile-link detection
  3. Update shared.js/library if X changed the data-testid, and re-run
  4. Retry after the page fully loads; transient hydration timing can hide the link

Example fix

// before (relies on logged-in home)
opencli twitter followers
// after (explicit target)
opencli twitter followers @elonmusk --limit 100
Defensive patterns

Strategy: try-catch

Validate before calling

const href = await page.evaluate(`() => document.querySelector('a[data-testid="AppTabBar_Profile_Link"]')?.getAttribute('href') ?? null`);
if (!href) throw new Error('Pass an explicit user: opencli twitter followers @handle');

Type guard

null

Try / catch

try {
  const rows = await opencli.twitter.followers();
} catch (err) {
  if (err instanceof AuthRequiredError && err.message.includes('profile link')) {
    const rows = await opencli.twitter.followers(myKnownHandle); // explicit-user fallback
  } else throw err;
}

Prevention

When it happens

Trigger: Running without a user argument while the profile link a[data-testid="AppTabBar_Profile_Link"] is missing from the rendered home page — logged-out state, X A/B test changing the testid, page not fully hydrated, or a localized/variant DOM.

Common situations: X front-end update renaming the data-testid; scraping before hydration completes; semi-logged-in state where ct0 exists but home renders logged-out chrome; running against an unsupported locale/layout experiment.

Related errors


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/65c29249cf11e67f. Report an issue: GitHub.