koala73/worldmonitor · error · SeedUnavailableError

${cacheKey}

Error message

${cacheKey}

What it means

SeedUnavailableError thrown by listWorldBankIndicators when the cachedFetchJsonWithMeta result is missing or its data.data field is not an array — i.e. the refresh callback returned an unexpected shape. The specific cacheKey (including indicator, countries, years, current year) is in the message.

Solutions

  1. Inspect the cacheKey in the message and check Redis for the stale/missing entry
  2. Verify fetchWorldBankIndicators still returns { data: [...] } matching ListWorldBankIndicatorsResponse
  3. Check recent refactors to either function for shape changes
  4. Retry after upstream recovery and confirm the seed repopulates
Defensive patterns

Strategy: type-guard

Validate before calling

if (!result?.data || !Array.isArray(result.data.data)) {
  throw new Error(`bad cached shape for ${cacheKey}`);
}

Type guard

function isValidIndicatorResponse(v: unknown): v is ListWorldBankIndicatorsResponse {
  return !!v && typeof v === 'object' && Array.isArray((v as any).data);
}

Try / catch

try {
  const res = await api.listWorldBankIndicators(req);
  if (!isValidIndicatorResponse(res)) throw new Error('shape');
  return res;
} catch {
  return { data: [], pagination: undefined };
}

Prevention

When it happens

Trigger: fetchWorldBankIndicators resolves but returns a value without a valid data array, or cachedFetchJsonWithMeta returns a stale/failed result the code treats as invalid; typically follows an upstream World Bank problem.

Common situations: World Bank API outage during cache refresh; a refactor changing the response shape of fetchWorldBankIndicators without updating this check; cache read returning a value typed differently than expected.

Understand the failure class

Background: "invalid response format", "malformed payload", "missing data field": when an API returns 200 but the response shape is wrong — this error's family across 23 libraries.

Related errors


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

Appendix: source

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

  req: ListWorldBankIndicatorsRequest,
): Promise<ListWorldBankIndicatorsResponse> {
  try {
    // The exported client accepts generic indicator codes, not just the tech
    // display catalogue. Bound their grammar without restricting that contract.
    if (req.indicatorCode.length > 64 || !/^[A-Z0-9_]+(?:\.[A-Z0-9_]+)+$/.test(req.indicatorCode)) {
      return { data: [], pagination: undefined };
    }
    const country = normalizeCountries(req.countryCode);
    if (country === null || !Number.isInteger(req.year)) return { data: [], pagination: undefined };
    // Match the existing World Bank relay's maximum lookback.
    const years = req.year > 0 ? Math.min(req.year, 30) : 5;
    const currentYear = new Date().getFullYear();
    const cacheKey = `${REDIS_CACHE_KEY}:${req.indicatorCode}:${country || '__default__'}:${years}:${currentYear}`;
    const result = await cachedFetchJsonWithMeta<ListWorldBankIndicatorsResponse>(cacheKey, REDIS_CACHE_TTL, async () => {
      const data = await fetchWorldBankIndicators(req.indicatorCode, country || TECH_COUNTRIES.join(';'), years, currentYear);
      return { data, pagination: undefined };
    }, 120, { cacheFailures: false });
    if (!result.data || !Array.isArray(result.data.data)) throw new SeedUnavailableError(cacheKey);
    return result.data;
  } catch {
    throw new SeedUnavailableError(REDIS_CACHE_KEY);
  }
}

View on GitHub (pinned to e586b8b4b8)