{"record":{"id":"25d86a80051d1558","repo":"jackwener/OpenCLI","slug":"label-returned-malformed-json-err-message-25d86a","errorCode":null,"errorMessage":"${label} returned malformed JSON: ${err?.message ?? err}","messagePattern":"(.+?) returned malformed JSON: (.+?)","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/npm/utils.js","lineNumber":73,"sourceCode":"    }\n    if (resp.status === 404) {\n        throw new EmptyResultError(label, `npm registry returned 404 for ${url}.`);\n    }\n    if (resp.status === 429) {\n        throw new CommandExecutionError(\n            `${label} returned HTTP 429 (rate limited)`,\n            'npm throttles unauthenticated bursts; wait a few seconds and retry.',\n        );\n    }\n    if (!resp.ok) {\n        throw new CommandExecutionError(`${label} returned HTTP ${resp.status}`);\n    }\n    let body;\n    try {\n        body = await resp.json();\n    }\n    catch (err) {\n        throw new CommandExecutionError(`${label} returned malformed JSON: ${err?.message ?? err}`);\n    }\n    return body;\n}\n","sourceCodeStart":55,"sourceCodeEnd":77,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/npm/utils.js#L55-L77","documentation":"After a successful HTTP response, npmFetch parses the body as JSON. If resp.json() throws — meaning the endpoint returned HTML, an error page, empty content, or truncated data instead of valid JSON — the helper wraps the parse failure in a CommandExecutionError noting the label and underlying parse message. This indicates the response did not come from a healthy JSON API endpoint.","triggerScenarios":"The registry or an intermediary returns non-JSON content for a URL that npmFetch expected to be JSON: a captive-portal/HTML login page from a proxy, an npm incident serving an HTML error page with 200 status, a truncated gzip body from a flaky connection, or an empty body from a misbehaving cache/CDN edge.","commonSituations":"Corporate networks or VPNs injecting HTML interstitial pages; malformed responses from custom registry mirrors or cached proxies; DNS hijacking redirects; requests that hit api.npmjs.org rate-limit pages with unexpected content types.","solutions":["Fetch the same URL with `curl -i <url>` and inspect the raw body to see what is actually being returned (HTML page? empty? proxy notice?)","Check whether a corporate proxy/captive portal is intercepting traffic and authenticate or bypass it","Retry after a short delay — intermittent truncation from flaky networks resolves on retry","Ensure requests go to the official endpoints (registry.npmjs.org, api.npmjs.org) and no overridden registry URL (npm config get registry) is mangling responses"],"exampleFix":"// before\nconst data = await npmFetch(url, 'npm package');\n// after\ntry {\n  const data = await npmFetch(url, 'npm package');\n} catch (err) {\n  if (String(err.message).includes('malformed JSON')) {\n    console.error('Registry returned non-JSON content; check proxy/network or retry.');\n  }\n  throw err;\n}","handlingStrategy":"retry","validationCode":"null","typeGuard":"null","tryCatchPattern":"try {\n  return await npmFetch(url, label);\n} catch (err) {\n  if (/malformed JSON/.test(String(err.message))) {\n    // Likely proxy/interstitial or truncated response — retry once\n    await sleep(500);\n    return await npmFetch(url, label);\n  }\n  throw err;\n}","preventionTips":["Verify network/proxy health: a captive portal or HTML-injecting proxy breaks JSON APIs","Pin requests to official endpoints; do not point the tool at a registry mirror that returns HTML","Retry transient truncations from flaky mobile/VPN connections","Inspect raw responses with `curl -i` when malformed-JSON errors repeat for the same URL"],"tags":["npm","json","malformed-response","network"],"backgroundTag":"malformed-json-response","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}