jackwener/OpenCLI · error · CommandExecutionError
toutiao hot-board returned status=${payload.status}
Error message
toutiao hot-board returned status=${payload.status} What it means
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).
Source
Thrown at clis/toutiao/hot.js:50
'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',
Accept: 'application/json',
Referer: 'https://www.toutiao.com/',
},
});
} catch (error) {
throw new CommandExecutionError(`toutiao hot-board request failed: ${error?.message || error}`);
}
if (!resp.ok) {
throw new CommandExecutionError(`toutiao hot-board failed: HTTP ${resp.status}`);
}
let payload;
try {
payload = await resp.json();
} catch (error) {
throw new CommandExecutionError(`toutiao hot-board returned malformed JSON: ${error?.message || error}`);
}
if (payload?.status && payload.status !== 'success') {
throw new CommandExecutionError(`toutiao hot-board returned status=${payload.status}`);
}
if (payload?.error || payload?.message) {
throw new CommandExecutionError(`toutiao hot-board returned error: ${payload.error || payload.message}`);
}
const list = Array.isArray(payload?.data) ? payload.data : [];
const rows = list.map(mapHotRow).filter(Boolean).slice(0, limit);
if (rows.length === 0) {
throw new EmptyResultError('toutiao hot', '上游 hot-board 返回空列表。');
}
// Re-rank (1..N) after filter so ranks are dense even if upstream had nulls.
return rows.map((row, idx) => ({ ...row, rank: idx + 1 }));
},
});
View on GitHub (pinned to 49907e53dc)
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.
Example fix
// before
if (payload?.status && payload.status !== 'success') {
throw new CommandExecutionError(`toutiao hot-board returned status=${payload.status}`);
}
// after — tolerate numeric success codes
const ok = payload?.status === 'success' || payload?.status === 0 || payload?.status === '0';
if (payload?.status !== undefined && !ok) {
throw new CommandExecutionError(`toutiao hot-board returned status=${payload.status}`);
} Defensive patterns
Strategy: type-guard
Validate before calling
// validate the envelope shape before trusting the data const isHotBoardPayload = (p) => p && typeof p === 'object' && (p.status === undefined || p.status === 'success') && (p.data === undefined || Array.isArray(p.data));
Type guard
function isHotBoardPayload(p) {
return (
p !== null && typeof p === 'object' &&
('status' in p ? p.status === 'success' : true) &&
('data' in p ? Array.isArray(p.data) : true)
);
} Try / catch
try {
const rows = await toutiaoHot({ limit: 30 });
} catch (e) {
if (/returned status=/.test(e.message)) {
// application-level upstream failure: inspect payload, wait, retry
await sleep(5000);
return toutiaoHot({ limit: 30 });
}
throw e;
} Prevention
- 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'.
When it happens
Trigger: 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).
Common situations: 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.
Related errors
- toutiao hot-board returned error: ${payload.error || payload
- archive item returned malformed payload: files must be an ar
- archive search failed: HTTP ${resp.status}
- archive search returned malformed payload: response.docs mus
- Ctrip flight API failed (status=${String(payload?.status)}):
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/d5fab89317983ace.
Report an issue: GitHub.