jackwener/OpenCLI · error · Error
JSON parse failed (status=${r.status}, body[0..50]=${JSON.st
Error message
JSON parse failed (status=${r.status}, body[0..50]=${JSON.stringify(trimmed.slice(0, 50))}): ${(err && err.message ? err.message : String(err))} What it means
This is the browser-side twin of the JSON parse guard: injected script code (embedded in a template string in src/utils.ts) that, after a fetch where r.ok, JSON.parses the text and on failure throws an Error with the status, a 50-char body preview, and the parser message. It surfaces malformed JSON to the Node side with enough context to debug without re-running in the browser.
Source
Thrown at src/utils.ts:206
const looksLikeHtml =
contentType.toLowerCase().includes('text/html')
|| /^<(?:!doctype|html|head|body|title)(?:[\\s>/]|$)/i.test(trimmed);
if (looksLikeHtml) {
return {
__loginWall: true,
status: r.status,
url: r.url || (typeof input === 'string' ? input : ''),
contentType,
bodyPreview: trimmed.slice(0, 100),
};
}
if (!r.ok) {
return { error: r.status };
}
try {
return JSON.parse(text);
} catch (err) {
throw new Error(
'JSON parse failed (status=' + r.status + ', body[0..50]=' + JSON.stringify(trimmed.slice(0, 50)) + '): '
+ (err && err.message ? err.message : String(err))
);
}
}
`;
View on GitHub (pinned to 49907e53dc)
Solutions
- Use the body[0..50] preview in the message to identify the actual payload
- Retry the in-page fetch; transient truncation is the most common cause
- Verify the endpoint URL is correct in the page context (relative URLs resolve against the page origin)
- Trim a leading BOM (\uFEFF) from the text before JSON.parse if previews show it
Example fix
// before const data = JSON.parse(text); // after const clean = text.replace(/^\uFEFF/, '').trim(); const data = JSON.parse(clean || 'null');
Defensive patterns
Strategy: retry
Validate before calling
// Inside the injected script, before parsing:
const clean = text.replace(/^\uFEFF/, '').trim();
if (!clean) return { error: r.status, body: '' }; Try / catch
try {
const data = await page.evaluate(script, url);
} catch (e) {
if (/JSON parse failed/.test(String(e.message))) { console.error('In-page JSON malformed — retry or log body preview'); }
throw e;
} Prevention
- Strip BOM/whitespace before JSON.parse in injected scripts
- Retry in-page fetches once on parse failure before surfacing the error
- Use absolute API URLs in page.evaluate to avoid origin-relative surprises
- Log the 50-char body preview included in the message when debugging
When it happens
Trigger: Running injected fetch/parse code inside page.evaluate against an endpoint that returns r.ok but a body JSON.parse cannot handle (empty body, HTML that escaped the earlier check, truncated JSON).
Common situations: Page context fetches to endpoints behind experiments returning empty 200s; SPA dev servers intercepting API routes; responses cut off by browser network conditions; endpoints emitting BOM or non-UTF8 bytes.
Related errors
- mdn search returned malformed JSON: ${err?.message ?? err}
- toutiao hot-board returned malformed JSON: ${error?.message
- JSON parse failed (status=${response.status}, body[0..50]=${
- ${label} returned a non-JSON response
- archive snapshots returned malformed JSON: ${error?.message
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/02908659079054da.
Report an issue: GitHub.