{"record":{"id":"ee7719a629c59603","repo":"koala73/worldmonitor","slug":"redis-cache-key","errorCode":null,"errorMessage":"${REDIS_CACHE_KEY}","messagePattern":"\\$\\{REDIS_CACHE_KEY\\}","errorType":"exception","errorClass":"SeedUnavailableError","httpStatus":503,"severity":"error","filePath":"server/worldmonitor/economic/v1/list-world-bank-indicators.ts","lineNumber":71,"sourceCode":"  indicator: string,\n  countryList: string,\n  years: number,\n  currentYear: number,\n): Promise<WorldBankCountryData[]> {\n  try {\n    const startYear = currentYear - years;\n\n    const wbUrl = `https://api.worldbank.org/v2/country/${encodeURIComponent(countryList)}/indicator/${encodeURIComponent(indicator)}?format=json&date=${startYear}:${currentYear}&per_page=1000`;\n\n    const response = await fetch(wbUrl, {\n      headers: {\n        Accept: 'application/json',\n        'User-Agent': CHROME_UA,\n      },\n      signal: AbortSignal.timeout(15000),\n    });\n\n    if (!response.ok) throw new SeedUnavailableError(REDIS_CACHE_KEY);\n\n    const data = await response.json();\n    if (!Array.isArray(data) || data.length < 2) throw new SeedUnavailableError(REDIS_CACHE_KEY);\n    if (data[1] === null && (data[0]?.total === 0 || data[0]?.total === '0')) return [];\n    if (!Array.isArray(data[1])) throw new SeedUnavailableError(REDIS_CACHE_KEY);\n\n    const records: any[] = data[1];\n    const indicatorName = records[0]?.indicator?.value || indicator;\n\n    return records\n      .filter((r: any) => r.countryiso3code && r.value !== null)\n      .map((r: any): WorldBankCountryData => ({\n        countryCode: r.countryiso3code || r.country?.id || '',\n        countryName: r.country?.value || '',\n        indicatorCode: indicator,\n        indicatorName,\n        year: parseInt(r.date, 10) || 0,\n        value: r.value,","sourceCodeStart":53,"sourceCodeEnd":89,"githubUrl":"https://github.com/koala73/worldmonitor/blob/e586b8b4b80f595aa7ece295eec10d76f2921240/server/worldmonitor/economic/v1/list-world-bank-indicators.ts#L53-L89","documentation":"SeedUnavailableError is thrown by fetchWorldBankIndicators when the World Bank API returns a non-OK HTTP status while fetching indicator records for the Redis seed. The Redis cache key is used as the error message to identify which seed dataset failed. It signals that fresh upstream data could not be obtained to populate the cache.","triggerScenarios":"The World Bank API (api.worldbank.org) returns 4xx/5xx for the given indicator/country/date URL, e.g. an invalid indicator code, rate limiting, or upstream outage, during the seed fetch inside cachedFetchJsonWithMeta's refresh callback.","commonSituations":"World Bank API rate limiting after bursts of requests; a renamed or removed indicator code; network egress blocked from the edge/worker; transient World Bank maintenance returning 5xx.","solutions":["Check the World Bank API URL/indicator code is valid by curling it directly","Retry after the transient upstream failure; the seed will repopulate on next request","Check network egress and User-Agent requirements for api.worldbank.org","Verify REDIS_CACHE_KEY/seed wiring so the failure surfaces for the right dataset"],"exampleFix":"// before\nif (!response.ok) throw new SeedUnavailableError(REDIS_CACHE_KEY);\n// after\nif (!response.ok) {\n  logCacheSeedError(REDIS_CACHE_KEY, `worldbank status ${response.status}`);\n  throw new SeedUnavailableError(REDIS_CACHE_KEY);\n}","handlingStrategy":"retry","validationCode":"const url = `https://api.worldbank.org/v2/country/${countries}/indicator/${indicator}?format=json&per_page=${perPage}`;\nconst probe = await fetch(url, { method: 'HEAD' });\nif (!probe.ok) throw new Error(`worldbank unavailable: ${probe.status}`);","typeGuard":null,"tryCatchPattern":"try {\n  const res = await api.listWorldBankIndicators(req);\n} catch (e) {\n  if (isSeedUnavailableError(e)) {\n    // backoff and retry; seed repopulates on recovery\n    await sleep(RETRY_DELAY_MS);\n    return retryOrServeStale();\n  }\n  throw e;\n}","preventionTips":["Pre-validate indicator codes against the World Bank indicator list","Add jittered backoff retry for upstream fetches","Monitor World Bank API status before running seed jobs","Keep a stale-cache fallback for seed failures"],"tags":["network","cache","world-bank","seed"],"backgroundTag":"upstream-api-error","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"}