{"record":{"id":"d5fab89317983ace","repo":"jackwener/OpenCLI","slug":"toutiao-hot-board-returned-status-payload-status","errorCode":null,"errorMessage":"toutiao hot-board returned status=${payload.status}","messagePattern":"toutiao hot-board returned status=(.+?)","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/toutiao/hot.js","lineNumber":50,"sourceCode":"                    'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36',\n                    Accept: 'application/json',\n                    Referer: 'https://www.toutiao.com/',\n                },\n            });\n        } catch (error) {\n            throw new CommandExecutionError(`toutiao hot-board request failed: ${error?.message || error}`);\n        }\n        if (!resp.ok) {\n            throw new CommandExecutionError(`toutiao hot-board failed: HTTP ${resp.status}`);\n        }\n        let payload;\n        try {\n            payload = await resp.json();\n        } catch (error) {\n            throw new CommandExecutionError(`toutiao hot-board returned malformed JSON: ${error?.message || error}`);\n        }\n        if (payload?.status && payload.status !== 'success') {\n            throw new CommandExecutionError(`toutiao hot-board returned status=${payload.status}`);\n        }\n        if (payload?.error || payload?.message) {\n            throw new CommandExecutionError(`toutiao hot-board returned error: ${payload.error || payload.message}`);\n        }\n        const list = Array.isArray(payload?.data) ? payload.data : [];\n        const rows = list.map(mapHotRow).filter(Boolean).slice(0, limit);\n        if (rows.length === 0) {\n            throw new EmptyResultError('toutiao hot', '上游 hot-board 返回空列表。');\n        }\n        // Re-rank (1..N) after filter so ranks are dense even if upstream had nulls.\n        return rows.map((row, idx) => ({ ...row, rank: idx + 1 }));\n    },\n});\n","sourceCodeStart":32,"sourceCodeEnd":64,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/toutiao/hot.js#L32-L64","documentation":"After parsing, the command checks payload.status; if the hot-board JSON reports a status other than 'success' this CommandExecutionError is thrown with the reported value. It means the API responded with valid JSON but signalled an application-level failure (e.g. status='error', 'fail', or a code string).","triggerScenarios":"Calling `toutiao hot` when Toutiao's endpoint returns a JSON envelope like {status:'error'} due to server-side throttling, maintenance, or a changed response contract (status field renamed/repurposed).","commonSituations":"Upstream API partially failing while still returning 200; Toutiao changing the response schema so status now carries a numeric code; regional restrictions returning a denial envelope.","solutions":["Log the full payload to see the exact status value and any accompanying message field.","Check the payload.message/error fields (the next check throws on those) for the upstream reason; retry if transient.","Compare the current live response from the endpoint with what this code expects and update the status check / mapping if Toutiao changed the contract.","If the endpoint is in maintenance, wait and retry later."],"exampleFix":"// before\nif (payload?.status && payload.status !== 'success') {\n  throw new CommandExecutionError(`toutiao hot-board returned status=${payload.status}`);\n}\n// after — tolerate numeric success codes\nconst ok = payload?.status === 'success' || payload?.status === 0 || payload?.status === '0';\nif (payload?.status !== undefined && !ok) {\n  throw new CommandExecutionError(`toutiao hot-board returned status=${payload.status}`);\n}","handlingStrategy":"type-guard","validationCode":"// validate the envelope shape before trusting the data\nconst isHotBoardPayload = (p) =>\n  p && typeof p === 'object' &&\n  (p.status === undefined || p.status === 'success') &&\n  (p.data === undefined || Array.isArray(p.data));","typeGuard":"function isHotBoardPayload(p) {\n  return (\n    p !== null && typeof p === 'object' &&\n    ('status' in p ? p.status === 'success' : true) &&\n    ('data' in p ? Array.isArray(p.data) : true)\n  );\n}","tryCatchPattern":"try {\n  const rows = await toutiaoHot({ limit: 30 });\n} catch (e) {\n  if (/returned status=/.test(e.message)) {\n    // application-level upstream failure: inspect payload, wait, retry\n    await sleep(5000);\n    return toutiaoHot({ limit: 30 });\n  }\n  throw e;\n}","preventionTips":["Snapshot a known-good API response and diff against it when statuses change.","Don't hard-code assumptions about the status string; tolerate numeric/alternate success codes if upstream evolves.","Retry on application-level failures — they are often transient upstream incidents.","Watch payload.message for hints when status !== 'success'."],"tags":["api","response-contract","upstream","cli"],"backgroundTag":"upstream-api-error-response","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}