{"record":{"id":"b2a63e6fae06ed9e","repo":"jackwener/OpenCLI","slug":"tiktok-studio-item-list-returned-an-empty-response","errorCode":null,"errorMessage":"TikTok Studio item_list returned an empty response","messagePattern":"TikTok Studio item_list returned an empty response","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/tiktok/creator-videos.js","lineNumber":110,"sourceCode":"  } catch (error) {\n    return {\n      ok: false,\n      status: 0,\n      statusText: '',\n      networkError: error instanceof Error ? error.message : String(error),\n    };\n  }\n})()\n`;\n}\n\nfunction looksAuthFailure(message) {\n    return /\\b(auth|login|log in|permission|unauthori[sz]ed|forbidden)\\b/i.test(message);\n}\n\nfunction unwrapPayload(data) {\n    if (!data || typeof data !== 'object') {\n        throw new CommandExecutionError('TikTok Studio item_list returned an empty response');\n    }\n    return data.data && typeof data.data === 'object' ? data.data : data;\n}\n\nfunction assertApiSuccess(data) {\n    const statusCode = data.status_code ?? data.statusCode;\n    const statusMsg = String(data.status_msg ?? data.statusMsg ?? '').trim();\n    if (statusCode !== undefined && Number(statusCode) !== 0) {\n        if (looksAuthFailure(statusMsg)) {\n            throw new AuthRequiredError('www.tiktok.com', `TikTok Studio item_list requires login: ${statusMsg || statusCode}`);\n        }\n        throw new CommandExecutionError(`TikTok Studio item_list failed: ${statusMsg || statusCode}`);\n    }\n    if (statusMsg && !/^(success|ok)$/i.test(statusMsg)) {\n        if (looksAuthFailure(statusMsg)) {\n            throw new AuthRequiredError('www.tiktok.com', `TikTok Studio item_list requires login: ${statusMsg}`);\n        }\n        throw new CommandExecutionError(`TikTok Studio item_list failed: ${statusMsg}`);","sourceCodeStart":92,"sourceCodeEnd":128,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/tiktok/creator-videos.js#L92-L128","documentation":"unwrapPayload checks the JSON body returned by TikTok Studio's item_list endpoint. If the response is null, undefined, or not an object, the library throws CommandExecutionError because it cannot extract data from an empty body. This guards against proxy/CDN error pages, empty 200 responses, or HTML returned instead of JSON.","triggerScenarios":"fetchCreatorVideosPage receives a non-object body (empty string parsed to null, HTML error page, or empty 200 response) from the TikTok Studio item_list request.","commonSituations":"Being behind a captive portal or corporate proxy returning an empty/HTML body; TikTok rate limiting with an empty response; expired session where the server returns a bare 200 with no body; intermittent network truncation.","solutions":["Retry the command once — empty bodies are often transient.","Verify you are logged in (`opencli tiktok login` / refresh cookies) since logged-out sessions can get empty responses.","Check for proxies/VPNs intercepting traffic and return non-JSON bodies.","Inspect the raw response (curl with the same cookies) to see what the server actually returned."],"exampleFix":"// before\nconst page = await fetchCreatorVideosPage(...); // throws on empty body\n// after\ntry {\n  const page = await fetchCreatorVideosPage(...);\n} catch (e) {\n  if (String(e.message).includes('empty response')) {\n    await sleep(2000);\n    return fetchCreatorVideosPage(...); // single retry for transient empty body\n  }\n  throw e;\n}","handlingStrategy":"retry","validationCode":"const res = await fetch(studioItemListUrl, { headers });\nconst text = await res.text();\nif (!text.trim()) throw new Error('Empty body from item_list; check login/proxy');\nconst data = JSON.parse(text);\nif (!data || typeof data !== 'object') throw new Error('item_list returned non-object body');","typeGuard":"const isPayloadObject = (v) => v !== null && typeof v === 'object' && !Array.isArray(v);","tryCatchPattern":"try {\n  const videos = await listCreatorVideos(opts);\n} catch (e) {\n  if (String(e.message).includes('empty response')) {\n    await sleep(2000);\n    const videos = await listCreatorVideos(opts); // one retry\n  } else throw e;\n}","preventionTips":["Ensure a valid TikTok session before calling; empty bodies often mean expired auth.","Disable intercepting proxies/VPNs that can return empty or HTML bodies.","Retry once with backoff for transient empty responses.","Log raw response bodies to diagnose non-JSON replies."],"tags":["network","empty-response","tiktok","api"],"backgroundTag":"empty-api-response","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}