jackwener/OpenCLI · error · CommandExecutionError
coingecko global returned malformed JSON: ${err?.message ??
Error message
coingecko global returned malformed JSON: ${err?.message ?? err} What it means
This CommandExecutionError is thrown when the CoinGecko /global endpoint returns an HTTP 200 response whose body cannot be parsed as JSON. The library wraps resp.json() in try/catch and rethrows with the underlying parse message. It signals an API-level response corruption problem, not a user input problem.
Source
Thrown at clis/coingecko/global.js:44
}
catch (err) {
throw new CommandExecutionError(`coingecko global request failed: ${err?.message ?? err}`);
}
if (resp.status === 429) {
throw new CommandExecutionError(
'coingecko returned HTTP 429 (rate limited)',
'Free tier allows ~30 calls/min. Wait and retry.',
);
}
if (!resp.ok) {
throw new CommandExecutionError(`coingecko global returned HTTP ${resp.status}`);
}
let body;
try {
body = await resp.json();
}
catch (err) {
throw new CommandExecutionError(`coingecko global returned malformed JSON: ${err?.message ?? err}`);
}
const data = body?.data;
if (!data) {
throw new CommandExecutionError('coingecko global returned no data envelope');
}
const totalMarketCap = data?.total_market_cap?.[currency];
const totalVolume = data?.total_volume?.[currency];
if (totalMarketCap == null && totalVolume == null) {
throw new ArgumentError(
`coingecko has no market totals for currency "${currency}"`,
'Use a CoinGecko-supported quote currency such as usd, cny, eur, or jpy.',
);
}
return [{
currency: currency.toUpperCase(),
totalMarketCap: totalMarketCap != null ? Number(totalMarketCap) : null,
totalVolume24h: totalVolume != null ? Number(totalVolume) : null,
marketCapChange24hPct: data.market_cap_change_percentage_24h_usd != null ? Number(data.market_cap_change_percentage_24h_usd) : null,View on GitHub (pinned to 49907e53dc)
Solutions
- Retry the command after a short wait — this is usually a transient response-corruption issue.
- Run the request manually (curl https://api.coingecko.com/api/v3/global) to inspect the raw body and see if it is HTML/Cloudflare content.
- Add or refresh a browser-like User-Agent / use a Pro API key if Cloudflare challenges are recurring.
- Check for a proxy or SSL-inspecting appliance mangling the response and bypass it.
- Clear any stale DNS/VPN interference and retry from a different network.
Example fix
// caller: tolerate transient malformed responses
// before
const rows = await runCli('coingecko', 'global');
// after
let rows;
try { rows = await runCli('coingecko', 'global'); }
catch (e) {
if (String(e.message).includes('malformed JSON')) await sleep(1000);
rows = await runCli('coingecko', 'global');
} Defensive patterns
Strategy: retry
Validate before calling
const ok = await fetch('https://api.coingecko.com/api/v3/ping').then(r => r.ok).catch(() => false);
if (!ok) throw new Error('coingecko unreachable right now'); Type guard
function isJsonObject(v) { return typeof v === 'object' && v !== null && !Array.isArray(v); } Try / catch
try {
rows = await runCli('coingecko', 'global');
} catch (e) {
if (String(e.message).includes('malformed JSON')) {
await new Promise(r => setTimeout(r, 2000));
rows = await runCli('coingecko', 'global');
} else throw e;
} Prevention
- Prefer a paid/Pro API key to avoid Cloudflare HTML challenges
- Route API traffic outside of inspecting proxies
- Retry with exponential backoff on parse failures
- Verify connectivity with /ping before long batch runs
When it happens
Trigger: fetch succeeded (resp.ok) but resp.json() throws: the endpoint returned HTML instead of JSON (e.g. Cloudflare challenge page), a truncated/garbled body, or a proxy/gateway intercepted the response.
Common situations: CoinGecko or Cloudflare serving a bot-challenge HTML page with 200 status; corporate proxies or firewalls rewriting responses; transient network interruption truncating the body; CoinGecko maintenance returning an HTML error page.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- 12306 queryByTrainNo returned non-JSON body
- 12306 ${endpoint} returned non-JSON body
- coingecko derivatives returned malformed JSON: ${err?.messag
- coingecko returned malformed JSON: ${error?.message || error
- ${label} returned malformed JSON: ${err?.message ?? err}
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/3ba4b8edd5668197.
Report an issue: GitHub.