jackwener/OpenCLI · error · CommandExecutionError

coingecko returned HTTP 429 (rate limited)

Error message

coingecko returned HTTP 429 (rate limited)

What it means

This CommandExecutionError is thrown when the CoinGecko trending endpoint responds with HTTP 429, meaning the client exceeded CoinGecko's rate limit. CoinGecko's free tier allows roughly 5-15 calls per minute per IP, so rapid repeated calls to the same endpoint trip this. The library detects the specific 429 status before the generic !resp.ok branch and attaches a remediation hint ('Wait and retry.').

Source

Thrown at clis/coingecko/trending.js:27

    site: 'coingecko',
    name: 'trending',
    access: 'read',
    description: 'Top trending cryptocurrencies on CoinGecko in the last 24h (search-volume based).',
    domain: 'api.coingecko.com',
    strategy: Strategy.PUBLIC,
    browser: false,
    args: [],
    columns: ['rank', 'id', 'symbol', 'name', 'marketCapRank', 'priceBtc', 'thumb'],
    func: async () => {
        const url = 'https://api.coingecko.com/api/v3/search/trending';
        let resp;
        try {
            resp = await fetch(url, { headers: { 'User-Agent': 'Mozilla/5.0' } });
        } catch (error) {
            throw new CommandExecutionError(`coingecko trending request failed: ${error?.message || error}`);
        }
        if (resp.status === 429) {
            throw new CommandExecutionError('coingecko returned HTTP 429 (rate limited)', 'Wait and retry.');
        }
        if (!resp.ok) {
            throw new CommandExecutionError(`coingecko trending failed: HTTP ${resp.status}`);
        }
        let data;
        try {
            data = await resp.json();
        } catch (error) {
            throw new CommandExecutionError(`coingecko returned malformed JSON: ${error?.message || error}`);
        }
        const coins = Array.isArray(data?.coins) ? data.coins : [];
        if (coins.length === 0) {
            throw new EmptyResultError('coingecko trending', 'coingecko returned no trending coins.');
        }
        return coins.map((entry, i) => {
            const c = entry?.item || {};
            return {
                rank: i + 1,

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Wait 60+ seconds and retry — 429 is transient
  2. Back off programmatically: catch the error and schedule a retry with exponential delay (e.g. 30s, 60s, 120s)
  3. Cache trending results and reduce call frequency (trending data changes slowly, hourly is plenty)
  4. Subscribe to CoinGecko's paid/demo API tier and attach an API key for higher rate limits

Example fix

// before
for (const _ of Array(20)) await runCli('coingecko trending'); // 429
// after
for (const _ of Array(20)) {
  await runCli('coingecko trending').catch(e => {
    if (/429/.test(e.message)) return sleep(60000);
    throw e;
  });
}
Defensive patterns

Strategy: retry

Validate before calling

const MIN_INTERVAL_MS = 15000;
let lastCall = 0;
function throttle() {
  const wait = lastCall + MIN_INTERVAL_MS - Date.now();
  if (wait > 0) Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, wait);
  lastCall = Date.now();
}
throttle(); // call before each coingecko command

Type guard

function isRateLimited(e) {
  return /HTTP 429|rate limited/i.test(e?.message || '');
}

Try / catch

try {
  await runCli('coingecko trending');
} catch (e) {
  if (isRateLimited(e)) {
    await new Promise(r => setTimeout(r, 60000));
    return runCli('coingecko trending');
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling the `coingecko trending` command too frequently from the same IP such that api.coingecko.com returns 429 Too Many Requests. The check is `if (resp.status === 429)` right after a successful fetch — any other non-OK status falls through to the generic HTTP error instead.

Common situations: CI pipelines polling trending data in a loop, cron jobs running more often than the rate-limit window, multiple scripts behind a shared NAT/proxy IP hitting the limit collectively, or running the command repeatedly during debugging.

Understand the failure class

Related errors


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