jackwener/OpenCLI · error · CommandExecutionError
${label} returned a malformed payload
Error message
${label} returned a malformed payload What it means
readDataArray in clis/juejin/utils.js:130 requires the API payload to be a non-null, non-array object that has its own `data` property. If the envelope lacks `data` entirely (or the payload is not an object), it throws this CommandExecutionError. It guards callers against Juejin changing or degrading its response shape.
Source
Thrown at clis/juejin/utils.js:130
}
let payload;
try {
payload = await resp.json();
} catch (err) {
throw new CommandExecutionError(`${label} returned malformed JSON: ${err?.message ?? err}`);
}
if (!payload || typeof payload !== 'object' || Array.isArray(payload) || !Object.hasOwn(payload, 'err_no')) {
throw new CommandExecutionError(`${label} returned a malformed API envelope`);
}
if (payload.err_no !== 0) {
throw new CommandExecutionError(`${label} returned err_no ${payload.err_no}: ${payload.err_msg ?? ''}`);
}
return payload;
}
export function readDataArray(payload, label) {
if (!payload || typeof payload !== 'object' || Array.isArray(payload) || !Object.hasOwn(payload, 'data')) {
throw new CommandExecutionError(`${label} returned a malformed payload`);
}
if (!Array.isArray(payload.data)) {
throw new CommandExecutionError(`${label} returned a non-array data field`);
}
if (payload.data.length === 0) {
throw new EmptyResultError(label, `${label} returned no articles.`);
}
return payload.data;
}
function readArticleId(value, label) {
const id = String(value ?? '').trim();
if (!JUEJIN_ID.test(id)) {
throw new CommandExecutionError(`${label} returned a malformed article id`);
}
return id;
}
View on GitHub (pinned to 49907e53dc)
Solutions
- Log the raw response body for the failing request to see what shape the API actually returned.
- Confirm the endpoint path and request body match the current Juejin API contract; update the adapter if the key was renamed.
- Check for an intercepting proxy or captive portal returning an unexpected JSON body with HTTP 200.
- Retry later — if it is a partial API rollout, the shape may revert; pin/report the contract change.
Example fix
// before: trusting the envelope blindly
const rows = readDataArray(await juejinFetch('/content_api/v1/article/query_list', body, 'juejin list'));
// after: defensive pre-check with diagnostics
const payload = await juejinFetch('/content_api/v1/article/query_list', body, 'juejin list');
if (!('data' in payload)) console.error('unexpected payload keys:', Object.keys(payload));
const rows = readDataArray(payload, 'juejin list'); Defensive patterns
Strategy: type-guard
Validate before calling
const payload = await resp.json();
if (payload == null || typeof payload !== 'object' || Array.isArray(payload) || !('data' in payload)) {
console.error('unexpected envelope:', JSON.stringify(payload).slice(0, 500));
} Type guard
function hasDataField(p) {
return p !== null && typeof p === 'object' && !Array.isArray(p)
&& Object.hasOwn(p, 'data');
} Try / catch
try {
const rows = readDataArray(payload, 'juejin list');
} catch (err) {
if (err instanceof CommandExecutionError && err.message.includes('malformed payload')) {
console.error('Envelope missing data field; dumping keys:', Object.keys(payload ?? {}));
return;
}
throw err;
} Prevention
- Log the raw HTTP body whenever the envelope looks wrong, so contract changes are visible.
- Check for proxies/captive portals that return HTTP 200 with a foreign JSON body.
- Pin and review Juejin API changes before deploying adapter updates.
- Route only list endpoints through readDataArray, never detail endpoints.
When it happens
Trigger: A juejinFetch result whose body parses as JSON but has no `data` key — e.g. the API returned `{ err_no: 0, err_msg: 'success' }` without data, an error object shape, or the endpoint silently changed its response contract.
Common situations: Juejin deploying an API revision that renames or omits `data`; a proxy/captive portal returning a 200 JSON page that is not the expected envelope; hitting an endpoint variant that nests results under a different key.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- eastmoney convertible returned malformed diff data
- ${label} returned a non-array data field
- ${label} returned a malformed article id
- Chess.com stats payload for ${kind} is not an object
- Chess.com stats payload for ${kind}.last is not an object
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/935c733285d64ccd.
Report an issue: GitHub.