koala73/worldmonitor · error · SeedUnavailableError

${REDIS_CACHE_KEY}

Error message

${REDIS_CACHE_KEY}

What it means

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.

Solutions

  1. Check the World Bank API URL/indicator code is valid by curling it directly
  2. Retry after the transient upstream failure; the seed will repopulate on next request
  3. Check network egress and User-Agent requirements for api.worldbank.org
  4. Verify REDIS_CACHE_KEY/seed wiring so the failure surfaces for the right dataset

Example fix

// before
if (!response.ok) throw new SeedUnavailableError(REDIS_CACHE_KEY);
// after
if (!response.ok) {
  logCacheSeedError(REDIS_CACHE_KEY, `worldbank status ${response.status}`);
  throw new SeedUnavailableError(REDIS_CACHE_KEY);
}
Defensive patterns

Strategy: retry

Validate before calling

const url = `https://api.worldbank.org/v2/country/${countries}/indicator/${indicator}?format=json&per_page=${perPage}`;
const probe = await fetch(url, { method: 'HEAD' });
if (!probe.ok) throw new Error(`worldbank unavailable: ${probe.status}`);

Try / catch

try {
  const res = await api.listWorldBankIndicators(req);
} catch (e) {
  if (isSeedUnavailableError(e)) {
    // backoff and retry; seed repopulates on recovery
    await sleep(RETRY_DELAY_MS);
    return retryOrServeStale();
  }
  throw e;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of koala73/worldmonitor@e586b8b4b8 (2026-09-22). Data as JSON: /api/errors/ee7719a629c59603. Report an issue: GitHub.

Appendix: source

Thrown at server/worldmonitor/economic/v1/list-world-bank-indicators.ts:71

  indicator: string,
  countryList: string,
  years: number,
  currentYear: number,
): Promise<WorldBankCountryData[]> {
  try {
    const startYear = currentYear - years;

    const wbUrl = `https://api.worldbank.org/v2/country/${encodeURIComponent(countryList)}/indicator/${encodeURIComponent(indicator)}?format=json&date=${startYear}:${currentYear}&per_page=1000`;

    const response = await fetch(wbUrl, {
      headers: {
        Accept: 'application/json',
        'User-Agent': CHROME_UA,
      },
      signal: AbortSignal.timeout(15000),
    });

    if (!response.ok) throw new SeedUnavailableError(REDIS_CACHE_KEY);

    const data = await response.json();
    if (!Array.isArray(data) || data.length < 2) throw new SeedUnavailableError(REDIS_CACHE_KEY);
    if (data[1] === null && (data[0]?.total === 0 || data[0]?.total === '0')) return [];
    if (!Array.isArray(data[1])) throw new SeedUnavailableError(REDIS_CACHE_KEY);

    const records: any[] = data[1];
    const indicatorName = records[0]?.indicator?.value || indicator;

    return records
      .filter((r: any) => r.countryiso3code && r.value !== null)
      .map((r: any): WorldBankCountryData => ({
        countryCode: r.countryiso3code || r.country?.id || '',
        countryName: r.country?.value || '',
        indicatorCode: indicator,
        indicatorName,
        year: parseInt(r.date, 10) || 0,
        value: r.value,

View on GitHub (pinned to e586b8b4b8)