{"record":{"id":"8cec989bea2c3365","repo":"jackwener/OpenCLI","slug":"coingecko-global-returned-http-resp-status","errorCode":null,"errorMessage":"coingecko global returned HTTP ${resp.status}","messagePattern":"coingecko global returned HTTP (.+?)","errorType":"http","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/coingecko/global.js","lineNumber":37,"sourceCode":"        const currency = String(args.currency ?? 'usd').trim().toLowerCase();\n        if (!/^[a-z0-9-]{2,20}$/.test(currency)) {\n            throw new ArgumentError(`coingecko currency must look like a currency slug (got \"${args.currency}\")`);\n        }\n        let resp;\n        try {\n            resp = await fetch('https://api.coingecko.com/api/v3/global', { headers: { 'User-Agent': 'Mozilla/5.0' } });\n        }\n        catch (err) {\n            throw new CommandExecutionError(`coingecko global request failed: ${err?.message ?? err}`);\n        }\n        if (resp.status === 429) {\n            throw new CommandExecutionError(\n                'coingecko returned HTTP 429 (rate limited)',\n                'Free tier allows ~30 calls/min. Wait and retry.',\n            );\n        }\n        if (!resp.ok) {\n            throw new CommandExecutionError(`coingecko global returned HTTP ${resp.status}`);\n        }\n        let body;\n        try {\n            body = await resp.json();\n        }\n        catch (err) {\n            throw new CommandExecutionError(`coingecko global returned malformed JSON: ${err?.message ?? err}`);\n        }\n        const data = body?.data;\n        if (!data) {\n            throw new CommandExecutionError('coingecko global returned no data envelope');\n        }\n        const totalMarketCap = data?.total_market_cap?.[currency];\n        const totalVolume = data?.total_volume?.[currency];\n        if (totalMarketCap == null && totalVolume == null) {\n            throw new ArgumentError(\n                `coingecko has no market totals for currency \"${currency}\"`,\n                'Use a CoinGecko-supported quote currency such as usd, cny, eur, or jpy.',","sourceCodeStart":19,"sourceCodeEnd":55,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/coingecko/global.js#L19-L55","documentation":"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).","triggerScenarios":"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.","commonSituations":"CoinGecko outages (check their status page), Cloudflare challenges for cloud-hosted workers, transient 502/503 during traffic spikes.","solutions":["Check the status code: retry 5xx later with backoff; investigate 4xx (IP blocked, endpoint changed) before retrying.","Consult the CoinGecko status page / X account for active incidents.","Retry transient 5xx with exponential backoff and a retry cap.","If 403/401 persists, switch networks or adopt an authenticated paid plan to bypass Cloudflare-level blocks."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  await globalCmd.func({ currency: 'usd' });\n} catch (e) {\n  const m = e.message.match(/HTTP (\\d{3})/);\n  if (m && m[1] >= 500) {\n    await sleep(5000);\n    return withRetry(() => globalCmd.func({ currency: 'usd' }), 3);\n  }\n  throw e;\n}","preventionTips":["Classify by status: 5xx retry with backoff, 4xx fix the request or network.","Subscribe to/monitor CoinGecko's status page for incidents.","Keep a small retry cap (2-3 attempts) for transient upstream failures.","For persistent 403s from cloud IPs, switch to an authenticated plan or different egress."],"tags":["http-error","upstream-api","coingecko"],"backgroundTag":"http-error-response","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}