jackwener/OpenCLI · error · CommandExecutionError
${label} returned malformed JSON: ${err?.message ?? err}
Error message
${label} returned malformed JSON: ${err?.message ?? err} What it means
packagistFetch throws this when resp.json() fails to parse the HTTP response body. It means the server responded but the payload was not valid JSON (HTML error page, truncated body, redirect page). The underlying parse error message is appended for diagnosis.
Source
Thrown at clis/packagist/utils.js:83
}
if (resp.status === 404) {
throw new EmptyResultError(label, `Packagist returned 404 for ${url}.`);
}
if (resp.status === 429) {
throw new CommandExecutionError(
`${label} returned HTTP 429 (rate limited)`,
'Packagist throttles bursts; 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;
}
/** Trim "2026-05-05T17:32:01+00:00" → "2026-05-05T17:32:01Z" so timestamps are uniform. */
export function trimDate(value) {
const s = String(value ?? '').trim();
if (!s) return null;
const noFrac = s.replace(/\.\d+/, '');
return noFrac.replace(/(?:[+-]\d{2}:?\d{2}|Z)?$/, 'Z');
}
/**
* Pick the newest stable (non-dev / non-prerelease) version key from a
* Packagist `versions` map. Packagist returns keys ordered newest-first.
* Falls back to the first key if no stable found.
*/
export function pickStableVersion(versions) {View on GitHub (pinned to 49907e53dc)
Solutions
- Retry the request — transient truncation is common.
- Check whether a proxy/firewall is intercepting and rewriting responses (look for HTML in the raw response).
- Verify the API endpoint URL has not changed or been redirected.
- Inspect err.message in the thrown error for the specific JSON parse failure.
Defensive patterns
Strategy: retry
Try / catch
try {
const data = await body(pkg);
} catch (err) {
if (/malformed JSON/.test(err.message)) {
// likely transient: retry with backoff
await sleep(2000);
return body(pkg);
}
throw err;
} Prevention
- Retry once or twice with backoff before failing.
- Bypass suspicious proxies when possible.
- Log the raw response text on parse failure for diagnosis.
When it happens
Trigger: Packagist or an intermediary returns HTML (error/captcha/redirect page) with 200, or the response body is truncated/corrupted mid-transfer.
Common situations: Captive portals or proxies injecting HTML into responses; CDN error pages; network interruption truncating the body; hitting a mirror that returns non-JSON.
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
- 12306 ${endpoint} returned an unexpected payload shape
- archive search returned malformed JSON: ${error?.message ||
- archive snapshots returned malformed JSON: ${error?.message
- archive wayback returned malformed JSON: ${error?.message ||
- Chess.com callback returned malformed JSON for ${url}: ${err
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/85e9e838cf7e850a.
Report an issue: GitHub.