{"record":{"id":"a78aab58e7df0298","repo":"jackwener/OpenCLI","slug":"cursor-must-be-a-safe-integer","errorCode":null,"errorMessage":"cursor must be a safe integer","messagePattern":"cursor must be a safe integer","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/tiktok/creator-videos.js","lineNumber":36,"sourceCode":"    const parsed = Number(raw);\n    if (!Number.isInteger(parsed) || parsed <= 0) {\n        throw new ArgumentError(`${label} must be a positive integer`, `Example: opencli tiktok creator-videos --${label} ${defaultValue}`);\n    }\n    if (parsed > maxValue) {\n        throw new ArgumentError(`${label} must be <= ${maxValue}`, `Example: opencli tiktok creator-videos --${label} ${maxValue}`);\n    }\n    return parsed;\n}\n\nfunction requireCursor(value) {\n    const raw = value ?? '0';\n    const text = String(raw).trim();\n    if (!/^\\d+$/.test(text)) {\n        throw new ArgumentError('cursor must be a non-negative integer string', 'Example: opencli tiktok creator-videos --cursor 0');\n    }\n    const cursor = Number(text);\n    if (!Number.isSafeInteger(cursor)) {\n        throw new ArgumentError('cursor must be a safe integer', 'Example: opencli tiktok creator-videos --cursor 0');\n    }\n    return cursor;\n}\n\nfunction buildItemListRequest(cursor, size) {\n    return {\n        cursor,\n        size,\n        query: {\n            conditions: [],\n            sort_orders: [{ field_name: 'create_time', order: 2 }],\n        },\n    };\n}\n\nfunction buildFetchItemListScript(body) {\n    const request = {\n        url: `${ITEM_LIST_API_PATH}?aid=1988`,","sourceCodeStart":18,"sourceCodeEnd":54,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/tiktok/creator-videos.js#L18-L54","documentation":"After the regex check passes, requireCursor converts the cursor to a JavaScript number and verifies it is a safe integer (within Number.MAX_SAFE_INTEGER). Extremely large digit strings that lose precision as doubles throw this ArgumentError, preventing silently wrong pagination offsets.","triggerScenarios":"Passing a cursor like --cursor 99999999999999999999 (more than ~15-16 digits) — matches /^\\d+$/ but Number(text) is not a safe integer.","commonSituations":"Pasting oversized/obfuscated numbers by mistake; a bug in the caller generating cursors; a TikTok response change producing cursor values the CLI can no longer represent.","solutions":["Use a smaller, previously-returned nextCursor value.","Restart pagination from --cursor 0.","If the server genuinely returns huge cursors, update the library to keep the cursor as a string instead of coercing to Number."],"exampleFix":"// before\nconst cursor = Number(text);\n// after\nconst cursor = Number(text);\nif (!Number.isSafeInteger(cursor)) {\n  throw new ArgumentError('cursor must be a safe integer', 'Example: opencli tiktok creator-videos --cursor 0');\n}","handlingStrategy":"validation","validationCode":"const cursor = String(process.env.TT_CURSOR ?? '0').trim();\nif (!/^\\d+$/.test(cursor) || !Number.isSafeInteger(Number(cursor))) {\n  throw new Error(`cursor '${cursor}' is not a safe non-negative integer`);\n}","typeGuard":"const isSafeCursor = (v) => /^\\d+$/.test(String(v).trim()) && Number.isSafeInteger(Number(String(v).trim()));","tryCatchPattern":"try {\n  await run(['tiktok', 'creator-videos', '--cursor', rawCursor]);\n} catch (e) {\n  if (String(e.message).includes('cursor must be a safe integer')) {\n    console.error(`Cursor ${rawCursor} exceeds safe integer range; restarting from 0`);\n    await run(['tiktok', 'creator-videos', '--cursor', '0']);\n  } else throw e;\n}","preventionTips":["Keep cursors within Number.MAX_SAFE_INTEGER; treat them as opaque strings from the previous response.","Reject oversized cursors in your own scripts before invoking the CLI.","Restart pagination from 0 if a stored cursor fails the safe-integer check."],"tags":["argument-validation","pagination","javascript","tiktok"],"backgroundTag":"invalid-argument-value","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}