jackwener/OpenCLI · error · CommandExecutionError
coingecko exchanges returned HTTP ${resp.status}
Error message
coingecko exchanges returned HTTP ${resp.status} What it means
CoinGecko returned a non-2xx status other than 429 and the library surfaces it as a CommandExecutionError containing the raw status code. This covers server-side rejections like 400/404 (bad query params), 401/403 (blocked or auth issues), and 5xx (CoinGecko outage).
Source
Thrown at clis/coingecko/exchanges.js:51
}
const url = new URL('https://api.coingecko.com/api/v3/exchanges');
url.searchParams.set('per_page', String(limit));
url.searchParams.set('page', String(page));
let resp;
try {
resp = await fetch(url, { headers: { 'User-Agent': 'Mozilla/5.0' } });
}
catch (err) {
throw new CommandExecutionError(`coingecko exchanges 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 exchanges returned HTTP ${resp.status}`);
}
let data;
try {
data = await resp.json();
}
catch (err) {
throw new CommandExecutionError(`coingecko exchanges returned malformed JSON: ${err?.message ?? err}`);
}
if (!Array.isArray(data) || !data.length) {
throw new EmptyResultError('coingecko exchanges', 'CoinGecko returned no exchange data.');
}
return data.map((ex, i) => ({
rank: (page - 1) * limit + i + 1,
id: String(ex.id ?? ''),
name: String(ex.name ?? ''),
trustScore: ex.trust_score != null ? Number(ex.trust_score) : null,
volume24hBtc: ex.trade_volume_24h_btc != null ? Number(ex.trade_volume_24h_btc) : null,
country: String(ex.country ?? ''),View on GitHub (pinned to 49907e53dc)
Solutions
- Read the status code in the message: 5xx means CoinGecko-side — retry later with backoff; 4xx means the request itself needs fixing.
- Check the CoinGecko status page or status.twitter/X for ongoing incidents.
- Retry transient 5xx with exponential backoff; do not retry 4xx blindly.
- If 403 persists, your IP may be blocked — try from a different network or add a valid API key/plan.
Example fix
// before
try { await exchanges.func({ page: 1 }); } catch (e) { throw e; }
// after
try {
await exchanges.func({ page: 1 });
} catch (e) {
if (/HTTP 5\d\d/.test(e.message)) await retryWithBackoff(() => exchanges.func({ page: 1 }));
else throw e;
} Defensive patterns
Strategy: try-catch
Try / catch
try {
await exchanges.func({ page: 1 });
} catch (e) {
const m = e.message.match(/HTTP (\d{3})/);
if (m && m[1] >= 500) retryLater(); // server-side: backoff + retry
else if (m && m[1] === 403) switchNetworkOrUseApiKey();
else throw e;
} Prevention
- Distinguish 5xx (retryable) from 4xx (fix request) before retrying.
- Watch the CoinGecko status page for incidents in monitoring setups.
- Cap retries to avoid hammering a struggling upstream.
- If 403 recurs, your IP is likely blocked — use a different network or authenticated plan.
When it happens
Trigger: Any resp.ok === false with status != 429 on /api/v3/exchanges: CoinGecko returning 5xx during an outage, a 400 from a malformed request, or a 401/403 if the client IP is blocked by Cloudflare protection.
Common situations: CoinGecko incidents (check status.coinantica/gecko status page), Cloudflare bot-protection blocking datacenter IPs, or transient 5xx during high load.
Understand the failure class
Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.
Related errors
- coingecko global returned HTTP ${resp.status}
- coingecko categories returned HTTP ${resp.status}
- coingecko trending failed: HTTP ${resp.status}
- No prices returned for train_no=${trainNo} ${fromStation.nam
- 12306 queryByTrainNo returned HTTP ${resp.status}
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/25d8a7f7ef0fec68.
Report an issue: GitHub.