{"record":{"id":"6fa310635fc40d10","repo":"jackwener/OpenCLI","slug":"tiktok-studio-item-list-failed-detail","errorCode":null,"errorMessage":"TikTok Studio item_list failed: ${detail}","messagePattern":"TikTok Studio item_list failed: (.+?)","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/tiktok/creator-videos.js","lineNumber":203,"sourceCode":"\nasync function fetchCreatorVideosPage(page, cursor, size) {\n    const result = await page.evaluate(buildFetchItemListScript(buildItemListRequest(cursor, size))).catch((error) => {\n        throw new CommandExecutionError(`Failed to fetch TikTok Studio item_list: ${getErrorMessage(error)}`);\n    });\n    if (!result || typeof result !== 'object') {\n        throw new CommandExecutionError('TikTok Studio item_list returned an unreadable response');\n    }\n    if (result.networkError) {\n        throw new CommandExecutionError(`TikTok Studio item_list network failure: ${result.networkError}`);\n    }\n    if (result.status === 401 || result.status === 403) {\n        throw new AuthRequiredError('www.tiktok.com', `TikTok Studio item_list requires login (HTTP ${result.status})`);\n    }\n    if (!result.ok) {\n        const detail = result.parseError\n            ? `invalid JSON (${result.parseError})`\n            : `HTTP ${result.status || 0}${result.statusText ? ` ${result.statusText}` : ''}`;\n        throw new CommandExecutionError(`TikTok Studio item_list failed: ${detail}`, result.text ? `Response preview: ${result.text}` : undefined);\n    }\n    const payload = unwrapPayload(result.data);\n    assertApiSuccess(payload);\n    return payload;\n}\n\nasync function listCreatorVideos(page, args) {\n    const limit = requirePositiveInt(args.limit, 'limit', DEFAULT_LIMIT, MAX_LIMIT);\n    let nextCursor = requireCursor(args.cursor);\n    const rows = [];\n    let skippedMissingId = 0;\n    const pageSize = limit > SERVER_PAGE_MAX ? SERVER_PAGE_MAX : limit;\n    const maxPages = Math.ceil(limit / pageSize);\n\n    await page.goto(STUDIO_CONTENT_URL, { waitUntil: 'load', settleMs: 6000 });\n\n    for (let pageIndex = 0; pageIndex < maxPages && rows.length < limit; pageIndex += 1) {\n        const data = await fetchCreatorVideosPage(page, nextCursor, pageSize);","sourceCodeStart":185,"sourceCodeEnd":221,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/tiktok/creator-videos.js#L185-L221","documentation":"item_list returned a non-2xx status (other than 401/403), or the response body was not valid JSON. The library builds a detail string ('invalid JSON (...)' or 'HTTP <status> <statusText>') and throws a CommandExecutionError, optionally attaching a response preview as a second argument.","triggerScenarios":"result.ok false: any 4xx/5xx besides 401/403 (429 rate limit, 5xx server error), or result.parseError set because the body wasn't JSON (HTML error page, login wall HTML, empty body).","commonSituations":"TikTok rate limiting (429) after heavy scraping, TikTok serving an HTML challenge/captcha page instead of JSON, regional blocks returning error pages, or TikTok API outages (5xx).","solutions":["Inspect the attached response preview (result.text) to see what TikTok actually returned","On HTTP 429, back off significantly (minutes, not seconds) and reduce request rate/page.wait values","If the preview shows HTML/captcha, solve the challenge in the browser profile before retrying","Retry on 5xx after a short delay — often transient TikTok server issues","Check the response statusText to distinguish rate limit vs server error"],"exampleFix":"// before\nconst rows = await listCreatorVideos(page, { limit: 100 });\n// after\ntry {\n  const rows = await listCreatorVideos(page, { limit: 100 });\n} catch (e) {\n  if (/HTTP 429/.test(e.message)) { await sleep(60000); /* retry with lower rate */ }\n  else throw e;\n}","handlingStrategy":"retry","validationCode":null,"typeGuard":"function isHttpFailure(r) { return !!r && typeof r === 'object' && r.ok === false && ![401,403].includes(r.status); }","tryCatchPattern":"try {\n  rows = await listCreatorVideos(page, opts);\n} catch (e) {\n  if (/HTTP 429/.test(e.message)) { await sleep(60000); /* reduce rate */ }\n  else if (/invalid JSON|HTTP 5\\d\\d/.test(e.message)) { await sleep(5000); /* retry */ }\n  else throw e;\n}","preventionTips":["Throttle request rate and keep page.wait delays generous to avoid 429s","Inspect the attached response preview for captcha/HTML challenge pages","Solve TikTok challenges in the browser profile before resuming automation","Retry 5xx failures after short backoff"],"tags":["tiktok","http-error","rate-limit","api"],"backgroundTag":"http-api-error","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}