{"record":{"id":"1c8fb26dc314b4ca","repo":"jackwener/OpenCLI","slug":"coingecko-returned-malformed-json-error-messag","errorCode":null,"errorMessage":"coingecko returned malformed JSON: ${error?.message || error}","messagePattern":"coingecko returned malformed JSON: (.+?)","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/coingecko/coin.js","lineNumber":66,"sourceCode":"        try {\n            resp = await fetch(url, { headers: { 'User-Agent': 'Mozilla/5.0' } });\n        } catch (error) {\n            throw new CommandExecutionError(`coingecko coin request failed: ${error?.message || error}`);\n        }\n        if (resp.status === 404) {\n            throw new EmptyResultError('coingecko coin', `coingecko has no coin with id \"${id}\".`);\n        }\n        if (resp.status === 429) {\n            throw new CommandExecutionError('coingecko returned HTTP 429 (rate limited)', 'Free tier allows ~30 calls/min. Wait and retry.');\n        }\n        if (!resp.ok) {\n            throw new CommandExecutionError(`coingecko coin failed: HTTP ${resp.status}`);\n        }\n        let data;\n        try {\n            data = await resp.json();\n        } catch (error) {\n            throw new CommandExecutionError(`coingecko returned malformed JSON: ${error?.message || error}`);\n        }\n        if (data?.error) {\n            throw new CommandExecutionError(`coingecko returned error: ${data.error}`);\n        }\n\n        const md = data.market_data || {};\n        const pick = (obj, key) => (obj && obj[key] != null ? obj[key] : null);\n        const isoFromMaybe = (s) => (s ? String(s).slice(0, 10) : '');\n        const price = pick(md.current_price, currency);\n        const marketCap = pick(md.market_cap, currency);\n        const volume24h = pick(md.total_volume, currency);\n        if (price == null && marketCap == null && volume24h == null) {\n            throw new CommandExecutionError(\n                `coingecko returned no market data for currency \"${currency}\"`,\n                'Use a CoinGecko-supported quote currency such as usd, cny, eur, or jpy.',\n            );\n        }\n","sourceCodeStart":48,"sourceCodeEnd":84,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/coingecko/coin.js#L48-L84","documentation":"This CommandExecutionError is thrown when resp.json() fails to parse the HTTP response body, meaning the server returned something that is not valid JSON (despite a 2xx status). The parse error message is interpolated for diagnosis.","triggerScenarios":"CoinGecko or an intermediary (proxy, captive portal, Cloudflare challenge page) returning HTML instead of JSON; truncated/garbled response bodies; content-encoding mismatches from MITM proxies.","commonSituations":"Corporate proxies rewriting responses; Wi-Fi captive portals intercepting the request; Cloudflare serving a challenge page to a flagged IP; CoinGecko maintenance returning an HTML error page with 200.","solutions":["Log or inspect the raw response text to see what was actually returned","Check for proxy/captive-portal interference and retry from a different network","Retry after a delay — often transient on the server side"],"exampleFix":"// before\ndata = await resp.json();\n// after\nconst text = await resp.text();\ntry { data = JSON.parse(text); } catch (e) { throw new Error(`non-JSON body: ${text.slice(0, 200)}`); }","handlingStrategy":"retry","validationCode":"null","typeGuard":"const looksLikeJson = (s) => { try { JSON.parse(s); return true; } catch { return false; } };","tryCatchPattern":"try { await run(['coingecko', 'coin', id]); } catch (e) { if (/malformed JSON/.test(e.message)) { await sleep(3000); return retryOnce(); } throw e; }","preventionTips":["Check for proxy/captive-portal interference if this recurs","Retry transiently — HTML error pages under 200 are usually short-lived","Verify the raw body with curl to distinguish environment issues from service issues"],"tags":["json","api-response","parsing"],"backgroundTag":"invalid-json-response","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}