{"record":{"id":"ff6d9cc34bd41960","repo":"jackwener/OpenCLI","slug":"failuremessage-message","errorCode":null,"errorMessage":"${failureMessage}: ${message}","messagePattern":"\\$\\{failureMessage\\}: \\$\\{message\\}","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/tiktok/utils.js","lineNumber":155,"sourceCode":"        videoId: match[2],\n    };\n}\n\nexport function looksTikTokAuthFailure(message) {\n    return /\\bAUTH_REQUIRED\\b|\\b(auth|captcha|login|log in|permission|unauthori[sz]ed|forbidden)\\b|HTTP\\s+(401|403)\\b/i.test(String(message || ''));\n}\n\nexport function looksTikTokUpstreamFailure(message) {\n    return /\\b(API failed|HTTP\\s+\\d+|invalid JSON|Failed to fetch|network|fetch)\\b/i.test(String(message || ''));\n}\n\nexport function throwTikTokPageContextError(error, { authMessage, emptyPattern, emptyTarget, failureMessage }) {\n    const message = getErrorMessage(error);\n    if (looksTikTokAuthFailure(message)) {\n        throw new AuthRequiredError('tiktok.com', authMessage);\n    }\n    if (looksTikTokUpstreamFailure(message)) {\n        throw new CommandExecutionError(`${failureMessage}: ${message}`);\n    }\n    if (emptyPattern.test(message)) {\n        throw new EmptyResultError(emptyTarget, message);\n    }\n    throw new CommandExecutionError(`${failureMessage}: ${message}`);\n}\n\n// Sentinels emitted by Route 1 (button-walker) IIFEs and mapped here to\n// typed errors. Keeping the strings constant in one place makes the IIFE\n// `throw new Error(...)` callsites greppable and the mapper exhaustive.\nexport const BUTTON_WALKER_SENTINELS = {\n    AUTH_REQUIRED: 'AUTH_REQUIRED',\n    BUTTON_NOT_FOUND: 'BUTTON_NOT_FOUND',\n    STATE_VERIFY_FAIL: 'STATE_VERIFY_FAIL',\n    RATE_LIMITED: 'RATE_LIMITED',\n};\n\n// Retryability for write-class typed errors. Captured in the hint string","sourceCodeStart":137,"sourceCodeEnd":173,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/tiktok/utils.js#L137-L173","documentation":"When the underlying error message matches looksTikTokUpstreamFailure (API failed / HTTP <code> / invalid JSON / Failed to fetch / network), the mapper wraps it in CommandExecutionError as '<failureMessage>: <message>'.","triggerScenarios":"Any of the page-context listing commands hits an upstream fetch failure: TikTok API returned an HTTP error, response was invalid JSON, or the in-page fetch threw a network error.","commonSituations":"TikTok rate-limiting or 5xx responses; corporate proxy blocking tiktok.com; flaky network/DNS during scraping; TikTok changing an internal API response shape (invalid JSON).","solutions":["Retry after a delay — upstream failures are often transient rate limits","Inspect the embedded upstream message for the HTTP status and address it (429 => back off longer)","Check network/proxy reachability of tiktok.com (curl -I https://www.tiktok.com)","Update the CLI if invalid JSON persists — TikTok may have changed its response format"],"exampleFix":"// before\nawait cli.listLive();\n// after\ntry { await cli.listLive(); }\ncatch (e) {\n  if (/rate|429/i.test(e.message)) await sleep(60_000);\n  await cli.listLive();\n}","handlingStrategy":"retry","validationCode":"// Pre-check connectivity\nawait fetch('https://www.tiktok.com', { method: 'HEAD' });","typeGuard":"const isUpstreamFailure = (e) => /\\b(API failed|HTTP\\s+\\d+|invalid JSON|Failed to fetch|network|fetch)\\b/i.test(e?.message ?? '');","tryCatchPattern":"try { return await cli.listExploreVideos(); } catch (e) { if (isUpstreamFailure(e) && attempts < 3) { await backoff(attempts); return retry(); } throw e; }","preventionTips":["Wrap listing calls in exponential-backoff retries","Monitor for HTTP 429/5xx and lengthen backoff accordingly","Pin/upgrade the CLI when 'invalid JSON' appears (API shape changed)"],"tags":["network","upstream-failure","scraping"],"backgroundTag":"upstream-fetch-failed","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}