jackwener/OpenCLI · error · CommandExecutionError
${label} returned malformed JSON: ${err?.message ?? err}
Error message
${label} returned malformed JSON: ${err?.message ?? err} What it means
After a 2xx response, wikidataFetch calls resp.json(). If the body cannot be parsed as JSON (truncated response, HTML error page from an intermediary, wrong content-type), it throws a CommandExecutionError noting the label and the underlying parse error.
Source
Thrown at clis/wikidata/utils.js:89
}
if (resp.status === 404) {
throw new EmptyResultError(label, `Wikidata returned 404 for ${url}.`);
}
if (resp.status === 429) {
throw new CommandExecutionError(
`${label} returned HTTP 429 (rate limited)`,
'Wikidata throttles anonymous traffic; back off and retry.',
);
}
if (!resp.ok) {
throw new CommandExecutionError(`${label} returned HTTP ${resp.status}`);
}
let body;
try {
body = await resp.json();
}
catch (err) {
throw new CommandExecutionError(`${label} returned malformed JSON: ${err?.message ?? err}`);
}
return body;
}
/**
* Pick a localised label / description from a `{<lang>: {value}}` map.
* Falls back to English if the requested language is missing.
*/
export function pickLocalised(map, language) {
if (!map || typeof map !== 'object') return null;
const direct = map[language];
if (direct && typeof direct.value === 'string' && direct.value.trim()) return direct.value;
if (language !== 'en' && map.en && typeof map.en.value === 'string' && map.en.value.trim()) {
return map.en.value;
}
return null;
}
View on GitHub (pinned to 49907e53dc)
Solutions
- Log resp status and a snippet of the raw text to see what was actually returned
- Verify network path — bypass proxies/VPNs and retry
- Retry the request; truncated responses are often transient
- Confirm the URL passed to wikidataFetch is a Wikidata API endpoint (.json / api.php)
Example fix
// before
const body = await wikidataFetch(url, 'entity');
// after
try {
const body = await wikidataFetch(url, 'entity');
} catch (err) {
if (String(err.message).includes('malformed JSON')) {
const raw = await fetch(url); console.log(await raw.text()); // inspect actual body
}
throw err;
} Defensive patterns
Strategy: try-catch
Type guard
function isJsonObject(v) { return v !== null && typeof v === 'object' && !Array.isArray(v); } Try / catch
try {
const body = await wikidataFetch(url, label);
} catch (err) {
if (String(err.message).includes('malformed JSON')) {
console.error('non-JSON body — check proxy/captive portal; retrying may help');
throw err;
}
throw err;
} Prevention
- Inspect raw response bodies when behind proxies/VPN
- Retry on transient truncation
- Verify the URL is a real Wikidata JSON endpoint
- Keep anti-virus/HTTPS-interception software from rewriting API traffic
When it happens
Trigger: An intermediary (proxy, captive portal, anti-bot page) returning HTML instead of the JSON API response; the connection dropping mid-body so JSON is truncated; a misconfigured URL pointing to a non-API endpoint that returns text/HTML.
Common situations: Corporate proxies or Wi-Fi captive portals injecting HTML login pages; inconsistent networking in containers/CI truncating large responses; fetching through a caching layer that serves an error page with 200.
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
- Chess.com callback returned malformed JSON for ${url}: ${err
- mdn search returned malformed JSON: ${err?.message ?? err}
- ${label} returned malformed JSON: ${err?.message ?? err}
- Malformed JSON from Stack Exchange API for ${label}: ${detai
- wikipedia returned malformed JSON: ${error?.message || error
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/aa3335411b5995d7.
Report an issue: GitHub.