{"record":{"id":"6647d494c59dccc1","repo":"koala73/worldmonitor","slug":"no-coinpaprika-id-mapping-for-stablecoins","errorCode":null,"errorMessage":"No CoinPaprika ID mapping for stablecoins","messagePattern":"No CoinPaprika ID mapping for stablecoins","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"scripts/seed-stablecoin-markets.mjs","lineNumber":53,"sourceCode":"async function fetchFromCoinGecko() {\n  const { baseUrl, headers } = coingeckoEndpoint();\n  const url = `${baseUrl}/coins/markets?vs_currency=usd&ids=${STABLECOIN_IDS}&order=market_cap_desc&sparkline=false&price_change_percentage=7d`;\n\n  const resp = await fetchCoinGeckoWithRetryBudget(url, {\n    headers,\n    requestTimeoutMs: REQUEST_TIMEOUT_MS,\n    budgetMs: COINGECKO_RETRY_BUDGET_MS,\n  });\n  const data = await resp.json();\n  if (!Array.isArray(data) || data.length === 0) {\n    throw new Error('CoinGecko returned no stablecoin data');\n  }\n  return data;\n}\n\nasync function fetchFromCoinPaprika() {\n  console.log('  [CoinPaprika] Falling back to CoinPaprika...');\n  if (COINPAPRIKA_IDS.length === 0) throw new Error('No CoinPaprika ID mapping for stablecoins');\n\n  const tickers = await fetchCoinPaprikaTickersById(COINPAPRIKA_IDS, {\n    concurrency: COINPAPRIKA_CONCURRENCY,\n    timeoutMs: REQUEST_TIMEOUT_MS,\n  });\n  const reverseMap = new Map(Object.entries(COINPAPRIKA_ID_MAP).map(([g, p]) => [p, g]));\n  return tickers\n    .map((t) => ({\n      id: reverseMap.get(t.id) || t.id,\n      current_price: t.quotes.USD.price,\n      price_change_percentage_24h: t.quotes.USD.percent_change_24h,\n      price_change_percentage_7d_in_currency: t.quotes.USD.percent_change_7d,\n      market_cap: t.quotes.USD.market_cap,\n      total_volume: t.quotes.USD.volume_24h,\n      symbol: t.symbol.toLowerCase(),\n      name: t.name,\n      image: '',\n    }));","sourceCodeStart":35,"sourceCodeEnd":71,"githubUrl":"https://github.com/koala73/worldmonitor/blob/e586b8b4b80f595aa7ece295eec10d76f2921240/scripts/seed-stablecoin-markets.mjs#L35-L71","documentation":"Thrown by fetchFromCoinPaprika when COINPAPRIKA_IDS is empty, meaning the CoinGecko->CoinPaprika ID mapping table has no entries, so the fallback source cannot request any tickers. This is a static configuration/invariant check that fires before any network call.","triggerScenarios":"COINPAPRIKA_ID_MAP (and derived COINPAPRIKA_IDS) is empty — typically because the map constant was removed, emptied, or conditionally defined based on config/env that is unset.","commonSituations":"A refactor dropped the ID map; an env/config gate defines the map only for certain environments; editing the stablecoin list emptied the mapped entries.","solutions":["Restore/populate COINPAPRIKA_ID_MAP with CoinGecko-id -> CoinPaprika-id pairs for the tracked stablecoins.","Check any env/config conditions that gate the map's definition and ensure they are satisfied in the seed environment.","Add a startup assertion (or this very check) so an empty map fails fast with a clear message.","Grep git history for the map constant if it was accidentally deleted in a refactor."],"exampleFix":"// before\nif (COINPAPRIKA_IDS.length === 0) throw new Error('No CoinPaprika ID mapping for stablecoins');\n// after\nif (COINPAPRIKA_IDS.length === 0) {\n  throw new Error('No CoinPaprika ID mapping for stablecoins — populate COINPAPRIKA_ID_MAP in seed-stablecoin-markets.mjs');\n}","handlingStrategy":"validation","validationCode":"if (!COINPAPRIKA_ID_MAP || Object.keys(COINPAPRIKA_ID_MAP).length === 0) throw new Error('COINPAPRIKA_ID_MAP is empty; populate before seeding');","typeGuard":"function hasIdMapping(map) { return !!map && typeof map === 'object' && Object.keys(map).length > 0; }","tryCatchPattern":"try { await fetchFromCoinPaprika(); } catch (e) { if (e.message === 'No CoinPaprika ID mapping for stablecoins') { console.error('Restore COINPAPRIKA_ID_MAP in seed-stablecoin-markets.mjs'); } throw e; }","preventionTips":["Assert the ID map is non-empty at module load, before any fetch","Keep the map in a reviewed constant file rather than generating it conditionally","Add a unit test that imports the seeder and checks COINPAPRIKA_IDS.length > 0","When extending the stablecoin list, add the corresponding CoinPaprika id in the same change"],"tags":["configuration","fallback","coincap","stablecoins"],"backgroundTag":"missing-required-config","analyzedSha":"e586b8b4b80f595aa7ece295eec10d76f2921240","analyzedAt":"2026-09-22T01:50:49.965Z","contentChangedAt":"2026-09-22T01:50:49.965Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}