{"record":{"id":"23984ef8a4305093","repo":"jackwener/OpenCLI","slug":"label-returned-malformed-json-err-message-23984e","errorCode":null,"errorMessage":"${label} returned malformed JSON: ${err?.message ?? err}","messagePattern":"(.+?) returned malformed JSON: (.+?)","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/osv/utils.js","lineNumber":92,"sourceCode":"export function requireBoundedInt(value, defaultValue, maxValue, label = 'limit') {\n    const raw = value ?? defaultValue;\n    const n = typeof raw === 'number' ? raw : Number(raw);\n    if (!Number.isInteger(n) || n <= 0) {\n        throw new ArgumentError(`osv ${label} must be a positive integer`);\n    }\n    if (n > maxValue) {\n        throw new ArgumentError(`osv ${label} must be <= ${maxValue}`);\n    }\n    return n;\n}\n\nasync function readJson(resp, label) {\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\nexport async function osvGet(url, label) {\n    let resp;\n    try {\n        resp = await fetch(url, { headers: { 'user-agent': UA, accept: 'application/json' } });\n    }\n    catch (err) {\n        throw new CommandExecutionError(\n            `${label} request failed: ${err?.message ?? err}`,\n            'Check that api.osv.dev is reachable from this network.',\n        );\n    }\n    if (resp.status === 404) {\n        throw new EmptyResultError(label, `OSV.dev returned 404 for ${url}.`);\n    }","sourceCodeStart":74,"sourceCodeEnd":110,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/osv/utils.js#L74-L110","documentation":"readJson calls resp.json() on the OSV API response; if the body is not valid JSON (HTML error pages, truncated responses, proxies), it wraps the parse failure in a CommandExecutionError prefixed with the request label.","triggerScenarios":"api.osv.dev or an intermediary (corporate proxy, captive portal, Cloudflare block page) returns non-JSON content with a 2xx/3xx status; response body truncated mid-stream.","commonSituations":"Corporate proxy injecting an HTML login page; rate limiting returning an HTML error; DNS hijacking; network flakiness truncating the body.","solutions":["Retry the request; transient truncation is common.","Check whether a proxy/firewall is intercepting api.osv.dev (curl the URL and inspect the body).","Bypass or correctly configure proxy env vars (HTTP_PROXY/HTTPS_PROXY).","Capture the full response body to see what was actually returned."],"exampleFix":"// before\nconst body = await readJson(resp, label); // throws on HTML body\n// after\ntry {\n  const body = await readJson(resp, label);\n} catch (e) {\n  console.error('Non-JSON response from OSV; check proxy/network:', e.message);\n}","handlingStrategy":"retry","validationCode":"const resp = await fetch(url);\nconst text = await resp.text();\ntry { JSON.parse(text); } catch { console.error('Non-JSON response, first 200 chars:', text.slice(0, 200)); }","typeGuard":"const isJsonObject = (v) =>\n  typeof v === 'object' && v !== null && !Array.isArray(v) &&\n  !Number.isNaN(Date.parse('x')) === false; // use JSON.parse in practice\n// practical guard:\nconst parsesAsJson = (text) => { try { JSON.parse(text); return true; } catch { return false; } };","tryCatchPattern":"try {\n  const body = await osvGet(url, label);\n} catch (e) {\n  if (e instanceof CommandExecutionError && /malformed JSON/.test(e.message)) {\n    console.error('OSV returned non-JSON (proxy/HTML page?) — inspect network path and retry');\n    return retryWithBackoff(() => osvGet(url, label), 3);\n  }\n  throw e;\n}","preventionTips":["Probe api.osv.dev with curl to detect proxy/captive-portal interference.","Configure HTTPS_PROXY/NO_PROXY correctly in CI and corporate networks.","Retry transient failures with exponential backoff.","Log the raw response body on JSON parse failure for diagnosis."],"tags":["network","json-parsing","http","proxy"],"backgroundTag":"malformed-json-response","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}