{"record":{"id":"83bec0af8d6516c0","repo":"jackwener/OpenCLI","slug":"coingecko-returned-no-category-data","errorCode":null,"errorMessage":"CoinGecko returned no category data.","messagePattern":"CoinGecko returned no category data\\.","errorType":"exception","errorClass":"EmptyResultError","httpStatus":null,"severity":"warning","filePath":"clis/coingecko/categories.js","lineNumber":63,"sourceCode":"        }\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 categories returned HTTP ${resp.status}`);\n        }\n        let data;\n        try {\n            data = await resp.json();\n        }\n        catch (err) {\n            throw new CommandExecutionError(`coingecko categories returned malformed JSON: ${err?.message ?? err}`);\n        }\n        if (!Array.isArray(data) || !data.length) {\n            throw new EmptyResultError('coingecko categories', 'CoinGecko returned no category data.');\n        }\n        return data.slice(0, limit).map((cat, i) => ({\n            rank: i + 1,\n            id: String(cat.id ?? ''),\n            name: String(cat.name ?? ''),\n            marketCap: cat.market_cap != null ? Number(cat.market_cap) : null,\n            volume24h: cat.volume_24h != null ? Number(cat.volume_24h) : null,\n            marketCapChange24hPct: cat.market_cap_change_24h != null ? Number(cat.market_cap_change_24h) : null,\n            top3Coins: Array.isArray(cat.top_3_coins_id) ? cat.top_3_coins_id.join(', ') : '',\n        }));\n    },\n});\n","sourceCodeStart":45,"sourceCodeEnd":76,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/coingecko/categories.js#L45-L76","documentation":"The API call succeeded and parsed, but the data was not a non-empty array, so the CLI throws EmptyResultError('coingecko categories'). This signals a genuinely empty or structurally unexpected payload rather than a transport failure.","triggerScenarios":"CoinGecko returns an empty array (no category data) or a non-array JSON object (e.g. an error/status object) from the categories endpoint.","commonSituations":"CoinGecko API behavior changes returning {status: {...}} error objects with HTTP 200; CoinGecko temporarily having no category data; version drift between the CLI and the API response shape.","solutions":["Retry later — likely a transient upstream data issue","Inspect the raw response body to confirm the payload shape","Update the CLI if CoinGecko changed the categories response format"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":"const data = await (await fetch(url)).json();\nif (!Array.isArray(data) || data.length === 0) {\n  console.warn('CoinGecko returned no category data; skipping');\n}","typeGuard":"function hasCategoryData(v) {\n  return Array.isArray(v) && v.length > 0 && typeof v[0] === 'object' && 'id' in (v[0] ?? {});\n}","tryCatchPattern":"try {\n  table = await runCategories(args);\n} catch (err) {\n  if (err instanceof EmptyResultError) {\n    table = []; // or fall back to cached data\n  } else throw err;\n}","preventionTips":["Cache the last successful category snapshot as a fallback","Handle HTTP-200 error objects ({status:{...}}) as empty results in wrappers","Pin/alert on CoinGecko API format changes; update the CLI when shapes drift"],"tags":["empty-result","data-shape","cli","coingecko"],"backgroundTag":"empty-result-set","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}