{"record":{"id":"4a9a4ae12c1da3cb","repo":"jackwener/OpenCLI","slug":"label-returned-invalid-json-4a9a4a","errorCode":null,"errorMessage":"${label} returned invalid JSON","messagePattern":"(.+?) returned invalid JSON","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/pubmed/utils.js","lineNumber":121,"sourceCode":"        throw new CommandExecutionError(`${label} request failed`, detail);\n    }\n    if (!response.ok) {\n        throw new CommandExecutionError(`${label} HTTP ${response.status}`, 'Check NCBI availability, request parameters, and optional NCBI_API_KEY.');\n    }\n    if (retmode === 'xml') {\n        return response.text();\n    }\n    try {\n        const json = await response.json();\n        assertNoEutilsError(json, label);\n        return json;\n    }\n    catch (error) {\n        if (error instanceof CommandExecutionError) {\n            throw error;\n        }\n        const detail = error instanceof Error ? error.message : String(error);\n        throw new CommandExecutionError(`${label} returned invalid JSON`, detail);\n    }\n}\n\nexport function assertNoEutilsError(json, label = 'PubMed E-utilities') {\n    const error = json?.error\n        || json?.esearchresult?.errorlist?.phrasesnotfound?.join(', ')\n        || json?.esearchresult?.errorlist?.fieldsnotfound?.join(', ');\n    if (error) {\n        throw new CommandExecutionError(`${label} returned an error`, String(error));\n    }\n}\n\nexport function buildPubMedUrl(pmid) {\n    return `https://pubmed.ncbi.nlm.nih.gov/${pmid}/`;\n}\n\nexport function decodeXmlEntities(value) {\n    return String(value ?? '')","sourceCodeStart":103,"sourceCodeEnd":139,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/pubmed/utils.js#L103-L139","documentation":"eutilsFetch wraps NCBI E-utilities HTTP calls and parses the JSON body when retmode is JSON. If response.json() throws (and the failure is not already a CommandExecutionError from assertNoEutilsError), it rethrows as `${label} returned invalid JSON` with the parse error as detail. The library throws this because it cannot distinguish an API problem from corrupted/non-JSON output, so it fails loudly instead of returning undefined data.","triggerScenarios":"Calling esearch, esummary/result, or eutilsFetch against an NCBI endpoint whose 200 response body is not valid JSON — e.g. an HTML error/interstitial page, a rate-limit or maintenance page, a proxy/captive portal injecting HTML, or a truncated response.","commonSituations":"NCBI throttling without an NCBI_API_KEY returning HTML instead of JSON; corporate proxies or VPNs rewriting responses; NCBI service outages; network middleware returning empty bodies with 200 status.","solutions":["Retry the call after a short delay; NCBI rate limits (3 req/s without API key) commonly trigger HTML throttle pages","Request a free NCBI_API_KEY and set it to raise the rate limit to 10 req/s","Check NCBI E-utilities status and network path (proxy/VPN) that may inject HTML","Inspect the `detail` field of the CommandExecutionError to see the exact JSON parse failure"],"exampleFix":"// before\nconst json = await esearch(query);\n// after\nlet json;\ntry {\n  json = await esearch(query);\n} catch (e) {\n  if (/returned invalid JSON/.test(e.message)) {\n    await new Promise(r => setTimeout(r, 1000)); // back off, then retry\n    json = await esearch(query);\n  } else throw e;\n}","handlingStrategy":"retry","validationCode":"// Validate the endpoint reachability before parsing\nconst res = await fetch(url);\nconst ct = res.headers.get('content-type') || '';\nif (!ct.includes('application/json')) throw new Error(`Expected JSON, got ${ct}`);","typeGuard":"function isJsonObject(v) {\n  return v !== null && typeof v === 'object' && !Array.isArray(v);\n}","tryCatchPattern":"try {\n  const json = await esearch(query);\n} catch (e) {\n  if (/returned invalid JSON/.test(e.message)) {\n    await backoff(1000);\n    return esearch(query); // retry once\n  }\n  throw e;\n}","preventionTips":["Set NCBI_API_KEY to avoid throttle responses that arrive as HTML","Check the response content-type before trusting JSON parsing","Add backoff/retry around E-utilities calls (respect 3 req/s limit)","Log the raw body on parse failure to detect proxies injecting HTML"],"tags":["network","json-parsing","pubmed","eutils"],"backgroundTag":"invalid-json-response","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}