jackwener/OpenCLI · error · CommandExecutionError
${label} returned malformed JSON: ${err?.message ?? err}
Error message
${label} returned malformed JSON: ${err?.message ?? err} What it means
Thrown by goproxyJson when the HTTP response body from proxy.golang.org cannot be parsed as JSON. The Go module proxy normally serves strict JSON documents (@latest, @v/<ver>.info), so a parse failure means the endpoint returned HTML (error page, block page, captive portal) or a truncated body instead. The library wraps the underlying SyntaxError in a CommandExecutionError with the offending label for context.
Source
Thrown at clis/goproxy/utils.js:90
throw new EmptyResultError(label, `proxy.golang.org returned ${resp.status} 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}`);
}
return resp;
}
export async function goproxyJson(url, label) {
const resp = await rawFetch(url, label);
let body;
try {
body = await resp.json();
}
catch (err) {
throw new CommandExecutionError(`${label} returned malformed JSON: ${err?.message ?? err}`);
}
return body;
}
export async function goproxyText(url, label) {
const resp = await rawFetch(url, label);
return resp.text();
}
// Sort version tags by their numeric components, newest first. Pre-release tags
// (anything after "-" that isn't a pure number) sort lower than the matching
// release. Returns a new sorted array; non-tag inputs are dropped.
export function sortVersionsDescending(versions) {
return versions
.filter((v) => typeof v === 'string' && VERSION_TAG.test(v))
.map((v) => ({ v, parts: parseSemver(v) }))
.sort((a, b) => compareParts(b.parts, a.parts))
.map((entry) => entry.v);View on GitHub (pinned to 49907e53dc)
Solutions
- Re-run the command to rule out a transient/truncated response
- Verify network access: curl the same URL and inspect whether the body is JSON or HTML
- Check for corporate proxies, VPNs, or captive portals intercepting traffic
- If using a custom GOPROXY endpoint, confirm it actually implements the GOPROXY JSON protocol
Example fix
// before
const data = await goproxyJson(url, 'goproxy latest');
// after
let data;
try { data = await goproxyJson(url, 'goproxy latest'); }
catch (e) { data = null; /* fall back or surface message */ } Defensive patterns
Strategy: try-catch
Validate before calling
// Preflight: confirm the endpoint serves JSON
const probe = await fetch(url);
const ct = probe.headers.get('content-type') || '';
if (!ct.includes('json')) throw new Error('endpoint did not return JSON: ' + ct); Type guard
function isJsonObject(v) { return v !== null && typeof v === 'object' && !Array.isArray(v); } Try / catch
try {
const body = await goproxyJson(url, 'goproxy latest');
} catch (err) {
// err is CommandExecutionError mentioning 'returned malformed JSON'
console.error('Proxy response was not JSON; check network/proxy interception.');
// optionally retry once or inspect via fetch + resp.text()
} Prevention
- Check Content-Type before parsing JSON responses
- Avoid relying on the CLI behind captive portals or rewriting corporate proxies
- Retry once on transient malformed responses
- Validate JSON shape before consuming fields
When it happens
Trigger: Calling goproxyJson(url, label) where fetch succeeded (2xx) but resp.json() throws: proxy returned an HTML error/interstitial page with 200 status, a captive portal or corporate proxy injected HTML, or the body was truncated mid-stream.
Common situations: Corporate proxies rewriting responses, DNS hijacking to a portal page, proxy.golang.org serving an unexpected maintenance page, network middleware corrupting the response, or pointing a custom command at a non-GOPROXY URL that returns HTML.
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
- archive snapshots returned malformed JSON: ${error?.message
- `${label} returned malformed JSON: ${err?.message ?? err}`
- mdn search returned malformed JSON: ${err?.message ?? err}
- ${label} returned malformed JSON: ${err?.message ?? err}
- ${label} returned malformed JSON: ${err?.message ?? err}
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/0e4a6f6794576a44.
Report an issue: GitHub.