jackwener/OpenCLI · error · CommandExecutionError

Twitter followers pagination repeated a cursor without retur

Error message

Twitter followers pagination repeated a cursor without returning new users

What it means

CommandExecutionError thrown when a pagination round of the twitter followers command produces no progress: the follower row count and the continuation cursor are identical to the values captured before the scroll. This means Twitter is serving the same cursor back without new users, so looping further would never finish. The library aborts instead of spinning forever.

Source

Thrown at clis/twitter/followers.js:190

                cursor = nextCursor;
            }
        };

        await consumeCaptured();
        while (allFollowers.length < limit && cursor && pages < MAX_PAGINATION_PAGES) {
            const beforeCount = allFollowers.length;
            const beforeCursor = cursor;
            await page.autoScroll({ times: 1, delayMs: 500 });
            try {
                await page.waitForCapture(CAPTURE_TIMEOUT_SECONDS);
            }
            catch {
                throw new TimeoutError('twitter followers pagination', CAPTURE_TIMEOUT_SECONDS, `Twitter returned a continuation cursor after ${allFollowers.length} rows, but the next Followers response was not observed.`);
            }
            await consumeCaptured();
            pages++;
            if (allFollowers.length === beforeCount && cursor === beforeCursor) {
                throw new CommandExecutionError('Twitter followers pagination repeated a cursor without returning new users');
            }
        }
        if (allFollowers.length < limit && cursor && pages >= MAX_PAGINATION_PAGES) {
            throw new CommandExecutionError(`Twitter followers pagination exceeded ${MAX_PAGINATION_PAGES} pages before cursor exhaustion`);
        }
        if (allFollowers.length === 0) {
            if (looksLikePrivateTwitterTimeline(lastRawResponse)) {
                throw new EmptyResultError('twitter followers', `No follower data returned for @${targetUser} (the target account may have set their followers list to private)`);
            }
            throw new EmptyResultError('twitter followers', `No followers found for @${targetUser}`);
        }
        return allFollowers.slice(0, limit);
    }
});

export const __test__ = {
    extractFollower,
    normalizeScreenName,

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Re-run the command; duplicated cursor responses are frequently transient on X's side.
  2. Log out/in or refresh ct0/auth_token cookies so X serves fresh timeline data.
  3. Lower --limit so the command finishes before reaching the degenerate page.
  4. Report/pin the account behavior — if it persists only for one target account, the account's follower timeline is likely restricted.

Example fix

// before
opencli twitter followers @restrictedaccount --limit 500
// after
opencli twitter followers @restrictedaccount --limit 100  # stop before the degenerate repeated-cursor page
Defensive patterns

Strategy: retry

Validate before calling

// No pre-call validation can detect server-side cursor loops; ensure a healthy logged-in session first:
const cookies = await page.getCookies({ url: 'https://x.com' });
if (!cookies.some(c => c.name === 'ct0')) throw new Error('Log into x.com before scraping');

Try / catch

try {
  rows = await opencli.twitter.followers(user, { limit });
} catch (e) {
  if (String(e.message).includes('repeated a cursor')) {
    rows = await opencli.twitter.followers(user, { limit: Math.min(limit, 100) }); // fresh session retry
  } else throw e;
}

Prevention

When it happens

Trigger: After consumeCaptured() of the next Followers response, allFollowers.length === beforeCount AND cursor === beforeCursor — Twitter returned a page whose only cursor is the same value already consumed and zero new user- entries.

Common situations: X GraphQL endpoint serving cached/duplicated timeline pages (server-side bug or A/B variant); a private/limited followers list where the API echoes the final cursor endlessly; stale session cookies making X replay the last good page; scraping an account whose followers were recently frozen.

Related errors


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