{"record":{"id":"923048227cd0cc1e","repo":"jackwener/OpenCLI","slug":"label-returned-malformed-json-err-message-923048","errorCode":null,"errorMessage":"${label} returned malformed JSON: ${err?.message ?? err}","messagePattern":"(.+?) returned malformed JSON: (.+?)","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/rfc/utils.js","lineNumber":59,"sourceCode":"            `${label} request failed: ${err?.message ?? err}`,\n            'Check that datatracker.ietf.org is reachable from this network.',\n        );\n    }\n    if (resp.status === 404) {\n        throw new EmptyResultError(label, `IETF datatracker returned 404 for ${url}.`);\n    }\n    if (resp.status === 429) {\n        throw new CommandExecutionError(`${label} returned HTTP 429 (rate limited)`);\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\n// IETF datatracker timestamps are like \"2022-02-19 08:46:51\" (no T, no Z)\n// or ISO with offset like \"2016-07-08T21:03:52+00:00\". Normalise to YYYY-MM-DD.\nexport function trimDate(value) {\n    const s = String(value ?? '').trim();\n    if (!s) return null;\n    // Take the first 10 chars only if they form a YYYY-MM-DD prefix.\n    if (/^\\d{4}-\\d{2}-\\d{2}/.test(s)) return s.slice(0, 10);\n    return null;\n}\n","sourceCodeStart":41,"sourceCodeEnd":73,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/rfc/utils.js#L41-L73","documentation":"rfcFetch in clis/rfc/utils.js fetches a URL from the IETF datatracker API and calls resp.json() on the response. When the HTTP 200 body cannot be parsed as JSON (SyntaxError from resp.json()), it is re-thrown as a CommandExecutionError with the label and the underlying parse message. The library throws this because a non-JSON body (HTML error page, proxy interception, truncation) means the datatracker response is unusable.","triggerScenarios":"rfcFetch (called by doc commands) receives a 2xx response whose body is not valid JSON: resp.json() throws and line 59 converts it to `${label} returned malformed JSON: ...`.","commonSituations":"Corporate proxy or captive portal returning an HTML login page with HTTP 200; datatracker serving an HTML error/interstitial page; response truncated by a flaky network or aggressive proxy; hitting a mirror or misconfigured RFC_BASE that returns HTML.","solutions":["Retry the same rfc/doc command; transient truncation or a proxy hiccup is the most common cause.","Check network/proxy settings: run `curl -s -H 'accept: application/json' <url>` and inspect whether the body is JSON or an HTML page.","Disable HTTPS interception/inspection on the proxy for datatracker.ietf.org, or bypass the proxy for that host (e.g. set NO_PROXY).","Wait and retry later if datatracker is degraded; if it persists, check the datatracker status or fall back to rfc-editor.org data."],"exampleFix":"// before: command dies with malformed-JSON error\nawait doc({ number: 9000 });\n\n// after: caller retries with fallback\ntry {\n  const info = await doc({ number: 9000 });\n} catch (e) {\n  if (/malformed JSON/.test(e.message)) {\n    // inspect raw body / retry once\n  }\n}","handlingStrategy":"try-catch","validationCode":"const resp = await fetch(url, { headers: { accept: 'application/json' } });\nconst text = await resp.text();\nif (!text.trim().startsWith('{') && !text.trim().startsWith('[')) {\n  throw new Error('datatracker returned non-JSON body: ' + text.slice(0, 120));\n}","typeGuard":"function isJsonObject(v) {\n  return v !== null && typeof v === 'object' && !Array.isArray(v);\n}","tryCatchPattern":"try {\n  const doc = await rfcFetch(url, 'rfc doc');\n} catch (e) {\n  if (/malformed JSON/.test(e.message)) {\n    // inspect raw response / bypass proxy / retry once\n  } else throw e;\n}","preventionTips":["Verify `curl -s <url> | head -c 200` returns JSON before blaming the library.","Bypass corporate proxies for datatracker.ietf.org (NO_PROXY) to avoid HTML interception pages.","Treat any 200-with-HTML as a network-layer problem, not a client bug."],"tags":["network","json","http","datatracker","proxy"],"backgroundTag":"malformed-json-response","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}