{"record":{"id":"5a08d5efbf36091f","repo":"jackwener/OpenCLI","slug":"douyin-api-error-code-at-method-url-ms","errorCode":null,"errorMessage":"Douyin API error ${code} at ${method} ${url}: ${msg}","messagePattern":"Douyin API error (.+?) at (.+?) (.+?): (.+?)","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/douyin/_shared/browser-fetch.js","lineNumber":69,"sourceCode":"        throw new CommandExecutionError(`Douyin API request failed (${method} ${url}): ${error instanceof Error ? error.message : String(error)}`);\n    }\n    if (result == null) {\n        throw new CommandExecutionError(\n            `Empty response from Douyin API (${method} ${url})`,\n            'The endpoint may have been retired or may now require signed parameters.',\n        );\n    }\n    if (Array.isArray(result) || typeof result !== 'object') {\n        throw new CommandExecutionError(`Malformed response from Douyin API (${method} ${url})`);\n    }\n    if (result && typeof result === 'object' && 'status_code' in result) {\n        const code = result.status_code;\n        if (code !== 0) {\n            const msg = result.status_msg ?? result.message ?? 'unknown error';\n            if (isAuthLikeError(code, msg)) {\n                throw new AuthRequiredError('creator.douyin.com', `Douyin API auth/permission error ${code} at ${method} ${url}: ${msg}`);\n            }\n            throw new CommandExecutionError(`Douyin API error ${code} at ${method} ${url}: ${msg}`);\n        }\n    }\n    return result;\n}\n","sourceCodeStart":51,"sourceCodeEnd":74,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/douyin/_shared/browser-fetch.js#L51-L74","documentation":"Generic Douyin API failure: the response carries a non-zero status_code that is not classified as an auth error, so browserFetch throws CommandExecutionError embedding the code, HTTP method, URL and the API-provided status_msg/message. It surfaces server-side business errors (rate limits, invalid params, content policy) to the caller.","triggerScenarios":"result.status_code !== 0 and isAuthLikeError(code, msg) is false — e.g. rate limiting, invalid parameters, forbidden content, or transient Douyin server errors.","commonSituations":"Publishing too frequently triggers rate limits; invalid video/cover IDs passed to the API; content rejected by review; transient 5xx-equivalent status codes during Douyin incidents.","solutions":["Read the embedded code/status_msg and look it up against Douyin's status code list to identify the business error.","If rate-limited, back off and retry after a delay (minutes, not seconds).","Validate the request parameters (IDs, titles, cover URIs) before re-issuing the call.","Retry once for transient codes; report/persist the failure if the code indicates a permanent rejection."],"exampleFix":"// before: blind immediate retry\nconst res = await browserFetch(page, api);\n// after: handle non-zero status_code with backoff\ntry {\n  const res = await browserFetch(page, api);\n} catch (e) {\n  const m = /error (\\d+)/.exec(e.message);\n  if (m && TRANSIENT_CODES.has(Number(m[1]))) {\n    await sleep(60_000);\n    return browserFetch(page, api);\n  }\n  throw e;\n}","handlingStrategy":"retry","validationCode":"null","typeGuard":"null","tryCatchPattern":"try {\n  return await browserFetch(page, api);\n} catch (e) {\n  const code = Number(/error (\\d+)/.exec(e.message)?.[1] ?? NaN);\n  if (TRANSIENT_DOUYIN_CODES.has(code)) {\n    await sleep(backoffMs);\n    return browserFetch(page, api);\n  }\n  throw e; // permanent business error — surface to user\n}","preventionTips":["Map Douyin status codes to transient vs permanent and retry only transient ones","Throttle request rate to avoid status_code rate-limit errors","Validate all request parameters before sending","Surface the embedded code/status_msg to users for diagnosis"],"tags":["douyin","api","status-code","rate-limit"],"backgroundTag":"api-business-error","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}