{"record":{"id":"5293b936e8d8988b","repo":"jackwener/OpenCLI","slug":"coingecko-derivatives","errorCode":null,"errorMessage":"coingecko derivatives","messagePattern":"coingecko derivatives","errorType":"exception","errorClass":"EmptyResultError","httpStatus":null,"severity":"warning","filePath":"clis/coingecko/derivatives.js","lineNumber":60,"sourceCode":"        }\n        if (resp.status === 429) {\n            throw new CommandExecutionError(\n                'coingecko derivatives 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 derivatives returned HTTP ${resp.status}`);\n        }\n        let data;\n        try {\n            data = await resp.json();\n        }\n        catch (err) {\n            throw new CommandExecutionError(`coingecko derivatives returned malformed JSON: ${err?.message ?? err}`);\n        }\n        if (!Array.isArray(data) || !data.length) {\n            throw new EmptyResultError('coingecko derivatives', 'CoinGecko returned no derivative tickers.');\n        }\n        let rows = data;\n        if (filter) {\n            rows = data.filter((d) => String(d.symbol ?? '').toUpperCase().includes(filter)\n                || String(d.index_id ?? '').toUpperCase().includes(filter));\n            if (!rows.length) {\n                throw new EmptyResultError('coingecko derivatives', `No derivative tickers matched symbol=\"${filter}\".`);\n            }\n        }\n        return rows.slice(0, limit).map((d, i) => ({\n            rank: i + 1,\n            market: String(d.market ?? ''),\n            symbol: String(d.symbol ?? ''),\n            indexId: String(d.index_id ?? ''),\n            contractType: String(d.contract_type ?? ''),\n            price: d.price != null ? Number(d.price) : null,\n            change24hPct: d.price_percentage_change_24h != null ? Number(d.price_percentage_change_24h) : null,\n            fundingRate: d.funding_rate != null ? Number(d.funding_rate) : null,","sourceCodeStart":42,"sourceCodeEnd":78,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/coingecko/derivatives.js#L42-L78","documentation":"EmptyResultError raised when the /derivatives endpoint returns valid JSON that is not a non-empty array. The library treats an empty or wrongly-shaped payload as 'no derivative tickers available' and signals it distinctly from a transport failure.","triggerScenarios":"API responds 200 with [] (no derivatives listed), or with a non-array JSON value such as {status: {...}} error object, null, or a string — e.g. an undocumented API schema change or a JSON error body that CoinGecko still serves with HTTP 200.","commonSituations":"CoinGecko quietly changing the /derivatives response shape; an outage page returning a JSON error object with 200; temporarily empty dataset during maintenance; caller parsing a cached/stale proxy response.","solutions":["Retry shortly — a transient empty payload often resolves.","Call the endpoint directly (curl) and inspect the JSON shape to confirm whether it is [] or a schema change.","Check CoinGecko status page / changelog for API schema or endpoint changes.","Pin to a known-good API version or add a Pro API key for more stable service.","If schema changed, update the CLI's mapping code to the new response format."],"exampleFix":"// before\nconst rows = await runCli(['coingecko', 'derivatives']);\n// after\ntry {\n  const rows = await runCli(['coingecko', 'derivatives']);\n} catch (err) {\n  if (err.name === 'EmptyResultError') {\n    return []; // treat 'no tickers' as an empty dataset, not a crash\n  }\n  throw err;\n}","handlingStrategy":"type-guard","validationCode":"const resp = await fetch('https://api.coingecko.com/api/v3/derivatives');\nconst data = await resp.json();\nif (!Array.isArray(data)) console.warn('Unexpected /derivatives schema:', typeof data, data);","typeGuard":"function hasDerivatives(v) {\n  return Array.isArray(v) && v.length > 0 && typeof v[0] === 'object' && v[0] !== null && 'symbol' in v[0];\n}","tryCatchPattern":"try {\n  const rows = await runCli(['coingecko', 'derivatives']);\n} catch (err) {\n  if (err.name === 'EmptyResultError') return []; // empty dataset, not fatal\n  throw err;\n}","preventionTips":["Treat EmptyResultError as 'no data', distinct from transport errors.","Pin/monitor the CoinGecko API schema; alert if /derivatives stops returning arrays.","Cache a last-known-good snapshot as a fallback dataset.","Check CoinGecko status/changelog when it happens repeatedly."],"tags":["empty-result","api-response","coingecko"],"backgroundTag":"empty-result-set","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}