jackwener/OpenCLI · error · CommandExecutionError

coingecko global returned HTTP ${resp.status}

Error message

coingecko global returned HTTP ${resp.status}

What it means

The /api/v3/global endpoint returned a non-2xx status other than 429, and the library throws a CommandExecutionError embedding the raw status code. 5xx indicates a CoinGecko-side problem; 4xx indicates the request was rejected (blocked IP, bad route, auth issue).

Source

Thrown at clis/coingecko/global.js:37

        const currency = String(args.currency ?? 'usd').trim().toLowerCase();
        if (!/^[a-z0-9-]{2,20}$/.test(currency)) {
            throw new ArgumentError(`coingecko currency must look like a currency slug (got "${args.currency}")`);
        }
        let resp;
        try {
            resp = await fetch('https://api.coingecko.com/api/v3/global', { headers: { 'User-Agent': 'Mozilla/5.0' } });
        }
        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.',

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Check the status code: retry 5xx later with backoff; investigate 4xx (IP blocked, endpoint changed) before retrying.
  2. Consult the CoinGecko status page / X account for active incidents.
  3. Retry transient 5xx with exponential backoff and a retry cap.
  4. If 403/401 persists, switch networks or adopt an authenticated paid plan to bypass Cloudflare-level blocks.
Defensive patterns

Strategy: try-catch

Try / catch

try {
  await globalCmd.func({ currency: 'usd' });
} catch (e) {
  const m = e.message.match(/HTTP (\d{3})/);
  if (m && m[1] >= 500) {
    await sleep(5000);
    return withRetry(() => globalCmd.func({ currency: 'usd' }), 3);
  }
  throw e;
}

Prevention

When it happens

Trigger: resp.ok === false with status != 429 on the global endpoint: CoinGecko 5xx during incidents or high load, 403 from Cloudflare bot protection on datacenter IPs, or unexpected 4xx from route/auth changes.

Common situations: CoinGecko outages (check their status page), Cloudflare challenges for cloud-hosted workers, transient 502/503 during traffic spikes.

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


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/8cec989bea2c3365. Report an issue: GitHub.