jackwener/OpenCLI · error · CommandExecutionError
twitter_collection_page_guard_hit
twitter_collection_page_guard_hit
Error message
twitter_collection_page_guard_hit: pagination cannot prove completion
What it means
If the for-loop over pageIndex completes maxPages iterations without reaching 'until' or exhausting the cursor, the pagination guard trips: the page budget ran out before completion could be proven. The library throws rather than returning an unverified, potentially gap-filled post set.
Source
Thrown at clis/twitter/collection.js:297
};
}
}
if (!nextCursor) {
return {
posts,
receipt: completedReceipt('cursor_exhausted', until, pageIndex + 1, oldestSeenAt),
};
}
if (nextCursor === cursor || seenCursors.has(nextCursor)) {
throw new CommandExecutionError('twitter_collection_repeated_cursor: pagination cannot prove completion');
}
if (posts.length >= limit) {
throw new CommandExecutionError('twitter_collection_limit_reached: pagination cannot prove completion');
}
seenCursors.add(nextCursor);
cursor = nextCursor;
}
throw new CommandExecutionError('twitter_collection_page_guard_hit: pagination cannot prove completion');
}
cli({
site: 'twitter',
name: 'collection',
access: 'read',
description: 'Fetch a user timeline with relationship facts and a bounded completion receipt.',
domain: 'x.com',
strategy: Strategy.COOKIE,
browser: true,
args: [
{ name: 'username', type: 'string', positional: true, required: true, help: 'Twitter screen name (with or without @).' },
{ name: 'until', type: 'string', required: true, help: 'RFC3339 lower time boundary that must be reached or exhausted.' },
{ name: 'limit', type: 'int', default: MAX_USER_TWEETS_LIMIT, help: 'Safety ceiling; reaching it is a typed failure.' },
{ name: 'page-delay', type: 'int', default: DEFAULT_USER_TWEETS_PAGE_DELAY_SECONDS, help: 'Seconds to wait between cursor pages.' },
],
columns: ['posts', 'receipt'],
func: async (page, kwargs) => {View on GitHub (pinned to 49907e53dc)
Solutions
- Increase maxPages so the page budget covers posts between now and 'until'.
- Narrow 'until' to a recent timestamp and collect incrementally across runs.
- Raise USER_TWEETS_PAGE_SIZE if X still honors it, reducing the number of pages required.
- Perform an initial full backfill once, then run frequent small incremental collections.
- Catch the error and persist oldestSeenAt from the receipt-building path to resume later.
Example fix
// before
const { posts } = await collection({ user: 'handle', until: '2026-01-01', maxPages: 5 });
// after
const { posts } = await collection({ user: 'handle', until: '2026-01-01', maxPages: 200 }); Defensive patterns
Strategy: try-catch
Validate before calling
const expectedPages = Math.ceil(expectedPosts / USER_TWEETS_PAGE_SIZE);
if (expectedPages > maxPages) {
console.warn(`maxPages ${maxPages} < estimated ${expectedPages} pages needed`);
} Try / catch
try {
const { posts } = await collection(...);
} catch (err) {
if (String(err.message).startsWith('twitter_collection_page_guard_hit')) {
// resume later using the oldest timestamp reached; raise maxPages for full backfill
} else throw err;
} Prevention
- Set maxPages to cover the full walk from newest post to 'until'.
- Do a one-time deep backfill, then frequent small incremental runs.
- Raise page size to reduce required page count.
- Track last collected timestamp to resume after guard hits.
- Don't reuse small maxPages tuned for one account against larger ones.
When it happens
Trigger: maxPages is smaller than the number of pages needed to walk from the newest post back to 'until' — common for high-volume accounts, old cutoffs, or small page sizes (USER_TWEETS_PAGE_SIZE).
Common situations: First-time deep backfill of a long-running account; 'until' set months back; rate-limit backoff shrinking usable pages; accounts with gaps/deleted tweets inflating page counts.
Related errors
- twitter_collection_limit_reached
- twitter_bookmarks_repeated_cursor
- twitter_bookmarks_archive_incomplete
- twitter_collection_invalid_timestamp
- twitter_collection_repeated_cursor
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/b3803e0da8035868.
Report an issue: GitHub.