{"record":{"id":"160b4536cdb6bb58","repo":"jackwener/OpenCLI","slug":"twitter-usermedia-pagination-reached-the-max-pag","errorCode":null,"errorMessage":"Twitter UserMedia pagination reached the ${MAX_PAGINATION_PAGES}-page safety cap before collecting ${limit} media items","messagePattern":"Twitter UserMedia pagination reached the (.+?)-page safety cap before collecting (.+?) media items","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/twitter/download.js","lineNumber":410,"sourceCode":"          if (!r.ok) return { ok: false, status: r.status };\n          return { ok: true, payload: await r.json() };\n        } catch (err) {\n          return { ok: false, error: err?.message ?? String(err) };\n        }\n        }`)));\n        const { items, nextCursor } = parseUserMedia(data, seen);\n        all.push(...items);\n        hasMorePages = Boolean(nextCursor);\n        if (!nextCursor) break;\n        if (nextCursor === cursor) {\n            throw new CommandExecutionError('Twitter UserMedia pagination returned the same cursor twice');\n        }\n        cursor = nextCursor;\n    }\n\n    if (all.length === 0) throw new EmptyResultError(`@${username} has no media`, 'Account may be private, suspended, or have no media posts');\n    if (all.length < limit && hasMorePages) {\n        throw new CommandExecutionError(`Twitter UserMedia pagination reached the ${MAX_PAGINATION_PAGES}-page safety cap before collecting ${limit} media items`);\n    }\n\n    const trimmed = all.slice(0, limit);\n    return downloadTwitterMedia(trimmed, {\n        output,\n        subdir: username,\n        cookies: formatCookieHeader(cookies),\n        browserCookies: cookies,\n        filenamePrefix: username,\n        ytdlpExtraArgs: ['--merge-output-format', 'mp4'],\n    });\n}\n\nasync function downloadSingleTweet(page, tweetUrl, output) {\n    const target = parseTweetUrl(tweetUrl);\n    await page.goto(target.url);\n    await page.wait(3);\n    const items = unwrapBrowserResult(await page.evaluate(`","sourceCodeStart":392,"sourceCodeEnd":428,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/twitter/download.js#L392-L428","documentation":"UserMedia pagination is capped at MAX_PAGINATION_PAGES iterations as a runaway-loop guard. If the loop ends having collected fewer items than --limit while the last response still advertised a next cursor, the command throws CommandExecutionError explaining the safety cap was reached before collecting the requested count.","triggerScenarios":"Requesting a large --limit (e.g. 500) on an account with abundant media where MAX_PAGINATION_PAGES pages of fetchCount-sized batches are insufficient, or pages returning fewer items than requested due to filtering/rate limiting.","commonSituations":"Setting --limit higher than what the page cap can deliver; Twitter returning truncated pages under rate limiting; duplicated items being deduplicated by `seen` so progress per page shrinks.","solutions":["Lower --limit to a value reachable within MAX_PAGINATION_PAGES pages","Re-run the command; transient truncation may resolve on retry","Raise MAX_PAGINATION_PAGES in the source if you maintain a fork and genuinely need deeper pagination"],"exampleFix":"// before\nopencli twitter download @jack --limit 500\n// after\nopencli twitter download @jack --limit 100","handlingStrategy":"fallback","validationCode":"const MAX_DELIVERABLE = MAX_PAGINATION_PAGES * ITEMS_PER_PAGE;\nif (limit > MAX_DELIVERABLE) {\n  limit = MAX_DELIVERABLE;\n  console.warn(`Limit reduced to ${limit} due to pagination cap`);\n}","typeGuard":null,"tryCatchPattern":"try {\n  return await cmd();\n} catch (err) {\n  if (err.message.includes('safety cap')) {\n    return runWithLowerLimit(err); // retry with a smaller --limit\n  }\n  throw err;\n}","preventionTips":["Choose --limit within what the page cap can deliver","Incremental runs (resume with larger limits) instead of one huge request","Expect this under rate-limited truncated pages and retry with a smaller limit"],"tags":["pagination","limits","twitter"],"backgroundTag":"pagination-limit-exceeded","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}