jackwener/OpenCLI · error · CommandExecutionError
Bilibili ${label} API returned a malformed payload
Error message
Bilibili ${label} API returned a malformed payload What it means
requireOkPayload enforces that a Bilibili API response is a non-null, non-array object containing a `code` field before interpreting it. If the body does not have this shape, the library cannot tell success from failure and throws instead of dereferencing undefined fields.
Source
Thrown at clis/bilibili/utils.js:228
const res = await fetch(${urlJs}, { credentials: "include" });
return await res.json();
}
`);
}
/**
* Bilibili write APIs return a JSON envelope `{ code, message, data }`. A non-zero
* `code` carries either an auth/permission failure (login expired, CSRF rejected,
* forbidden) or an application-level error (rate limit, validation, etc.). These
* two helpers route the envelope to the right typed error so every write adapter
* surfaces login problems as `AuthRequiredError`, not a generic execution error.
*/
export function isAuthLikeBilibiliError(code, message) {
return code === -101 || code === -111 || code === -403 || /csrf|登录|账号|权限|forbidden|permission|login/i.test(String(message ?? ''));
}
export function requireOkPayload(payload, label) {
if (!payload || typeof payload !== 'object' || Array.isArray(payload) || !Object.hasOwn(payload, 'code')) {
throw new CommandExecutionError(`Bilibili ${label} API returned a malformed payload`);
}
if (payload.code !== 0) {
const message = payload.message ?? 'unknown error';
if (isAuthLikeBilibiliError(payload.code, message)) {
throw new AuthRequiredError('bilibili.com', `Bilibili ${label} API requires login or permission: ${message} (${payload.code})`);
}
throw new CommandExecutionError(`Bilibili ${label} API failed: ${message} (${payload.code})`);
}
return payload.data;
}
/**
* POST form-encoded params to a Bilibili API endpoint.
* Runs inside the logged-in browser context and auto-attaches the bili_jct CSRF token,
* which Bilibili requires on every authenticated write request.
*/
export async function apiPost(page, path, opts = {}) {
const params = opts.params ?? {};View on GitHub (pinned to 49907e53dc)
Solutions
- Log the raw HTTP status and body — if it's HTML, you were likely blocked by risk control; slow down or send proper headers/cookies.
- Ensure the response was parsed with response.json() and that parsing succeeded before calling requireOkPayload.
- Check that requests include a realistic User-Agent and Referer; missing headers often trigger non-JSON block pages.
- If a proxy/CDN is interfering, retry or route around it; verify the endpoint URL is correct.
Example fix
// before const payload = await res.text(); // string, not parsed JSON requireOkPayload(payload, 'view'); // after const payload = await res.json(); requireOkPayload(payload, 'view');
Defensive patterns
Strategy: try-catch
Validate before calling
const text = await res.text();
let payload; try { payload = JSON.parse(text); } catch { throw new Error(`Non-JSON Bilibili response (HTTP ${res.status}): ${text.slice(0,200)}`); } Type guard
function isBiliPayload(p){ return !!p && typeof p==='object' && !Array.isArray(p) && Object.hasOwn(p,'code'); } Try / catch
try { const data = requireOkPayload(payload, 'view'); } catch (e) { if (/malformed payload/.test(e.message)) { logRawBody(); /* likely anti-bot HTML or unparsed body */ } throw e; } Prevention
- Always parse responses with response.json() and handle parse failure before requireOkPayload.
- Send realistic User-Agent/Referer headers to avoid HTML risk-control pages.
- Check HTTP status; 412/403 from WAF returns non-JSON bodies.
- Log raw bodies on parse/shape failures to distinguish blocking from schema drift.
When it happens
Trigger: Passing a payload to requireOkPayload(payload, label) that is null, undefined, an Array, a primitive, or an object without a `code` property — e.g., raw fetch text never parsed as JSON, an HTML error page, or an empty 204 body.
Common situations: Bilibili returning an HTML anti-bot/risk-control page (HTTP 412/403) with a non-JSON body; response.json() failing upstream and null being passed along; a WAF/CDN block page; network middleware returning empty bodies on 304.
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
- ${label} returned an unexpected payload shape; expected an o
- 获取到的视频播放信息对象不符合预期格式
- Bilibili view API returned a malformed ${label}
- Bilibili view API did not return pages[] for --page selectio
- Bilibili view API returned a malformed pages[] entry
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/6d6dad5db7e31dba.
Report an issue: GitHub.