jackwener/OpenCLI · error · CommandExecutionError

twitter_collection_request_error

twitter_collection_request_error

Error message

twitter_collection_request_error: UserTweets returned ${payload.error}

What it means

paginateCollection checks each UserTweets payload for an error property before parsing. If the GraphQL response carries an error (auth failure, rate limit, bad cursor, etc.), the library surfaces it as twitter_collection_request_error including the API's own error text, aborting pagination since no completeness can be proven from an errored page.

Source

Thrown at clis/twitter/collection.js:265

        completed: true,
        stop_reason: stopReason,
        requested_until: until.toISOString(),
        pages_fetched: pagesFetched,
        oldest_seen_at: oldestSeenAt ? oldestSeenAt.toISOString() : null,
    };
}

async function paginateCollection({ until, limit, maxPages = MAX_USER_TWEETS_PAGES, fetchPage, wait }) {
    const seen = new Set();
    const seenCursors = new Set();
    const posts = [];
    let cursor = null;
    let oldestSeenAt = null;
    for (let pageIndex = 0; pageIndex < maxPages; pageIndex++) {
        if (pageIndex > 0 && wait) await wait();
        const payload = await fetchPage(cursor, USER_TWEETS_PAGE_SIZE);
        if (payload?.error) {
            throw new CommandExecutionError(`twitter_collection_request_error: UserTweets returned ${payload.error}`);
        }
        const [pagePosts, nextCursor] = parseCollectionPage(payload, seen);
        for (const post of pagePosts) {
            if (posts.length >= limit) {
                throw new CommandExecutionError('twitter_collection_limit_reached: pagination cannot prove completion');
            }
            const createdAt = parseCreatedAt(post);
            if (!oldestSeenAt || createdAt < oldestSeenAt) oldestSeenAt = createdAt;
            posts.push(post);
            if (createdAt <= until) {
                return {
                    posts,
                    receipt: completedReceipt('time_boundary_reached', until, pageIndex + 1, oldestSeenAt),
                };
            }
        }
        if (!nextCursor) {
            return {

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Read payload.error in the message and address the specific X error (rate limit → back off and retry later; auth → refresh cookies/session).
  2. Refresh authentication before long collection runs to avoid mid-pagination token expiry.
  3. Update the library's queryId/GraphQL operation hashes if X deployed a new frontend version.
  4. Add exponential backoff between pages instead of a fixed wait.
  5. Reduce maxPages/page size to stay under rate limits for large accounts.

Example fix

// before
for (let pageIndex = 0; pageIndex < maxPages; pageIndex++) {
  if (pageIndex > 0 && wait) await wait();
// after
for (let pageIndex = 0; pageIndex < maxPages; pageIndex++) {
  if (pageIndex > 0 && wait) await wait(Math.min(baseDelay * 2 ** pageIndex, cap)); // backoff against rate limits
Defensive patterns

Strategy: retry

Validate before calling

if (payload?.error) {
  console.error('X GraphQL error before pagination:', payload.error);
  return;
}

Type guard

function isCleanPayload(payload) {
  return payload != null && typeof payload === 'object' && !('error' in payload);
}

Try / catch

try {
  await paginateCollection(...);
} catch (err) {
  if (String(err.message).startsWith('twitter_collection_request_error')) {
    await backoffRetry(maxAttempts, baseDelayMs); // handle rate limit / auth errors
  } else throw err;
}

Prevention

When it happens

Trigger: fetchPage returns a payload with truthy .error — X GraphQL errors such as rate limiting (429/TooManyRequests), expired auth cookies, invalid queryId after an X deploy, or cursor invalidated by account changes.

Common situations: Long-running paginations exceeding X rate limits; stale queryId in the bundled GraphQL request after X ships a new frontend build; expired guest/session token mid-run; network proxy injecting error JSON.

Related errors


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