jackwener/OpenCLI · error · CommandExecutionError
${label} returned malformed JSON: ${err?.message ?? err}
Error message
${label} returned malformed JSON: ${err?.message ?? err} What it means
This CommandExecutionError is thrown by nugetFetch in clis/nuget/utils.js when resp.json() fails — the server returned an HTTP-ok response whose body is not valid JSON (or the connection was truncated mid-body). The library expects all NuGet endpoints to return JSON (it sends accept: application/json) so a non-JSON body indicates an intercepted or malformed response.
Source
Thrown at clis/nuget/utils.js:73
`${label} request failed: ${err?.message ?? err}`,
'Check that api.nuget.org is reachable from this network.',
);
}
if (resp.status === 404) {
throw new EmptyResultError(label, `NuGet returned 404 for ${url}.`);
}
if (resp.status === 429) {
throw new CommandExecutionError(`${label} returned HTTP 429 (rate limited)`);
}
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;
}
export function joinTags(tags) {
if (!Array.isArray(tags)) return '';
return tags.filter((t) => typeof t === 'string' && t.trim()).join(', ');
}
export function joinAuthors(authors) {
if (Array.isArray(authors)) return authors.filter((a) => typeof a === 'string' && a.trim()).join(', ');
if (typeof authors === 'string') return authors.trim();
return '';
}
View on GitHub (pinned to 49907e53dc)
Solutions
- Inspect the raw response (curl the URL) to see what body is actually returned
- Bypass or reconfigure the intercepting proxy / complete captive-portal login
- Retry the request — truncation is often transient
- Check NODE_EXTRA_CA_CERTS / TLS setup if a corporate appliance is rewriting traffic
Example fix
// before
const data = await nugetFetch(url, 'search'); // throws on HTML body
// after
try {
const data = await nugetFetch(url, 'search');
} catch (e) {
if (String(e.message).includes('malformed JSON')) {
// fall back or retry — likely proxy/captive portal
}
throw e;
} Defensive patterns
Strategy: fallback
Validate before calling
null
Type guard
null
Try / catch
try {
const data = await nugetFetch(url, 'search');
} catch (e) {
if (e instanceof CommandExecutionError && e.message.includes('malformed JSON')) {
await sleep(1000);
return nugetFetch(url, 'search'); // truncated/proxied response; retry
}
throw e;
} Prevention
- Complete captive-portal logins before running network scripts
- Bypass SSL-inspection proxies for *.nuget.org or trust their CA via NODE_EXTRA_CA_CERTS
- Retry on malformed JSON — truncation is often transient
- Inspect raw responses with curl when it recurs consistently
When it happens
Trigger: A proxy or captive portal returning an HTML login/error page with status 200; TLS-intercepting middleboxes rewriting responses; truncated response bodies on flaky networks; a CDN edge returning an HTML error page.
Common situations: Hotel/airport Wi-Fi captive portals; corporate SSL inspection appliances; very large search responses cut off by an aggressive proxy timeout.
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
- archive search returned malformed JSON: ${error?.message ||
- archive snapshots returned malformed JSON: ${error?.message
- archive wayback returned malformed JSON: ${error?.message ||
- COMMAND_EXEC
- ${label} returned malformed JSON: ${err?.message ?? err}
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/54caecbf7983865e.
Report an issue: GitHub.