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 successful HTTP response, cratesFetch parses the body with resp.json(); if that throws, it raises `"${label} returned malformed JSON: ..."` as a CommandExecutionError. This means the endpoint responded with a 2xx but the payload was not valid JSON (or was truncated), so the response could be a proxy error page, HTML, or a partial body.
Source
Thrown at clis/crates/utils.js:69
}
if (resp.status === 404) {
throw new EmptyResultError(label, `crates.io returned 404 for ${url}.`);
}
if (resp.status === 429) {
throw new CommandExecutionError(
`${label} returned HTTP 429 (rate limited)`,
'crates.io rate-limits unauthenticated traffic; wait a few seconds 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;
}
View on GitHub (pinned to 49907e53dc)
Solutions
- Check what the endpoint actually returns: `curl -i <url>` and inspect the raw body for HTML/proxy text.
- Disable or bypass any intercepting proxy/VPN/captive portal and retry.
- Retry the command — truncation from transient network issues is common.
- If it persists on a specific endpoint, report it; the adapter may need to track a crates.io API format change.
Defensive patterns
Strategy: retry
Try / catch
try {
const data = await opencli.crates.info(name);
} catch (err) {
if (err.message.includes('malformed JSON')) {
// bypass proxy / retry once after short delay
}
throw err;
} Prevention
- Run `curl -i <crates.io url>` when on suspicious networks to spot HTML/proxy responses.
- Avoid captive portals and intercepting proxies for API traffic.
- Retry on flaky networks; truncation is usually transient.
- Keep TLS inspection exceptions for crates.io in corporate environments.
When it happens
Trigger: cratesFetch receives an OK response whose body fails JSON.parse: an intercepting proxy/captive portal returning HTML, a truncated response, or a changed endpoint returning a non-JSON format.
Common situations: Corporate proxies or antivirus rewriting responses; hotel/airport Wi-Fi captive portals; very large responses cut off by a middlebox; crates.io serving an HTML error page with 200.
Understand the failure class
Background: "Invalid JSON response" and "Failed to parse response" errors: when an API answers 200 but the body isn't the JSON your library expected — this error's family across 28 libraries.
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Chess.com API returned malformed JSON for ${url}: ${error?.m
- ${label} returned malformed JSON: ${err?.message ?? err}
- 12306 ${endpoint} returned an unexpected payload shape
- archive search returned malformed JSON: ${error?.message ||
- archive snapshots returned malformed JSON: ${error?.message
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/0f5b32fd61ebfc63.
Report an issue: GitHub.