jackwener/OpenCLI · error · TimeoutError

twitter followers API capture

Error message

twitter followers API capture

What it means

The command triggers an SPA navigation to /{user}/followers and waits up to CAPTURE_TIMEOUT_SECONDS (10s) for the intercepted /Followers GraphQL request via page.waitForCapture. If no matching response is observed in time, the wait's rejection is converted into a TimeoutError naming the operation and timeout. This means X never issued (or the interceptor never saw) a Followers API call after the navigation.

Source

Thrown at clis/twitter/followers.js:142

                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 {
            await page.waitForCapture(CAPTURE_TIMEOUT_SECONDS);
        }
        catch {
            throw new TimeoutError('twitter followers API capture', CAPTURE_TIMEOUT_SECONDS, 'No Followers response was observed after opening the followers list.');
        }
        const currentPath = unwrapBrowserResult(await page.evaluate('() => window.location.pathname'));
        if (typeof currentPath !== 'string' || !currentPath.toLowerCase().endsWith('/followers')) {
            throw new CommandExecutionError('SPA navigation to Twitter followers failed');
        }

        const allFollowers = [];
        const seen = new Set();
        let cursor = null;
        let lastRawResponse = null;
        let pages = 0;

        const consumeCaptured = async () => {
            const requests = await page.getInterceptedRequests();
            if (!Array.isArray(requests)) {
                throw new CommandExecutionError('Twitter followers interceptor returned malformed responses');
            }
            for (const request of requests) {

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Retry — transient slowness often resolves; consider increasing CAPTURE_TIMEOUT_SECONDS
  2. Verify you can open https://x.com/{user}/followers manually in the same browser profile
  3. Try a different target account (the target may be private/suspended)
  4. Update the interceptor pattern in followers.js if X renamed the Followers endpoint
  5. Re-authenticate if the page is redirecting to login

Example fix

// before
const CAPTURE_TIMEOUT_SECONDS = 10;
// after
const CAPTURE_TIMEOUT_SECONDS = 30;
Defensive patterns

Strategy: retry

Validate before calling

// pre-check that the followers page loads for this account
const res = await fetch('https://x.com/' + handle + '/followers', { headers: { cookie } });
if (res.redirected && res.url.includes('/login')) throw new Error('auth wall for ' + handle);

Type guard

null

Try / catch

try {
  const rows = await opencli.twitter.followers(user, { limit });
} catch (err) {
  if (err instanceof TimeoutError && err.message.includes('API capture')) {
    await sleep(3000);
    return opencli.twitter.followers(user, { limit }); // one retry
  } else throw err;
}

Prevention

When it happens

Trigger: The followers page requires login (redirect to /login), the account is suspended/protected so no Followers request fires, the interceptor pattern '/Followers?' no longer matches X's endpoint path, the popstate navigation failed, or the network is slow beyond 10 seconds.

Common situations: Target account is private/suspended so X never loads the followers list; X changed the GraphQL operation path; x.com is serving a login wall despite a ct0 cookie; heavy rate-limiting or a network hiccup.

Related errors


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