jackwener/OpenCLI · error · CommandExecutionError

coingecko top request failed: ${error?.message || error}

Error message

coingecko top request failed: ${error?.message || error}

What it means

This CommandExecutionError is thrown when the fetch() call itself rejects — the request never completed, so there is no HTTP status. The library wraps the network error and rethrows with the original message. Typical root causes are DNS failures, connection refused/reset, TLS errors, or timeouts.

Source

Thrown at clis/coingecko/top.js:39

    if (!Number.isInteger(limit) || limit <= 0) {
      throw new ArgumentError('limit must be a positive integer');
    }
    if (limit > 250) {
      throw new ArgumentError('limit must be <= 250 (CoinGecko per_page upper bound)');
    }

    const url = new URL('https://api.coingecko.com/api/v3/coins/markets');
    url.searchParams.set('vs_currency', currency);
    url.searchParams.set('order', 'market_cap_desc');
    url.searchParams.set('per_page', String(limit));
    url.searchParams.set('page', '1');
    url.searchParams.set('sparkline', 'false');

    let resp;
    try {
      resp = await fetch(url, { headers: { 'User-Agent': 'Mozilla/5.0' } });
    } catch (error) {
      throw new CommandExecutionError(`coingecko top request failed: ${error?.message || error}`);
    }
    if (!resp.ok) throw new CommandExecutionError(`coingecko top failed: HTTP ${resp.status}`);
    let data;
    try {
      data = await resp.json();
    } catch (error) {
      throw new CommandExecutionError(`coingecko returned malformed JSON: ${error?.message || error}`);
    }
    if (data?.error) throw new CommandExecutionError(`coingecko returned error: ${data.error}`);
    if (!Array.isArray(data)) throw new CommandExecutionError('coingecko returned an unexpected response');
    if (data.length === 0) throw new EmptyResultError('coingecko top', 'coingecko returned no market data');

    return data.map((c) => ({
      rank: c.market_cap_rank,
      symbol: String(c.symbol ?? '').toUpperCase(),
      name: c.name,
      price: c.current_price,
      change24hPct: c.price_change_percentage_24h,

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Check basic connectivity (curl https://api.coingecko.com/api/v3/ping) and retry.
  2. Fix DNS/network issues: try a different DNS server (1.1.1.1) or network.
  3. If the domain is blocked in your region/network, use a VPN or HTTPS proxy (HTTPS_PROXY env var).
  4. Configure a longer timeout or retry with exponential backoff for transient outages.
  5. Verify system clock and CA certificates if the message indicates a TLS error.

Example fix

// before
const rows = await runCli('coingecko', 'top');
// after
const rows = await retry(async () => runCli('coingecko', 'top'), { retries: 3, factor: 2 });
Defensive patterns

Strategy: retry

Validate before calling

const reachable = await fetch('https://api.coingecko.com/api/v3/ping', { signal: AbortSignal.timeout(5000) })
  .then(r => r.ok).catch(() => false);
if (!reachable) throw new Error('api.coingecko.com is unreachable from this network');

Type guard

null

Try / catch

async function withRetry(fn, attempts = 3) {
  for (let i = 0; ; i++) {
    try { return await fn(); }
    catch (e) {
      if (i >= attempts - 1 || !/request failed|ECONN|ENOTFOUND|timeout/i.test(e.message)) throw e;
      await new Promise(r => setTimeout(r, 2 ** i * 1000));
    }
  }
}
const rows = await withRetry(() => runCli('coingecko', 'top'));

Prevention

When it happens

Trigger: api.coingecko.com unreachable: DNS resolution failure, no internet/VPN blocking, TLS handshake failure, request timeout/abort, connection reset by a firewall or GFW-style block.

Common situations: Offline laptop or dead Wi-Fi; corporate firewall blocking crypto-related domains; IPv6 misconfiguration; DNS hijacking; CoinGecko regional blocks requiring a proxy/VPN.

Related errors


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