koala73/worldmonitor · error · SeedUnavailableError

series

Error message

${BLS_CANONICAL_KEY} series ${req.seriesId}

What it means

getBlsSeries serves BLS series from a Redis seed cache. If no servable (valid-envelope) series matching req.seriesId is found in the seed, it throws SeedUnavailableError naming BLS_CANONICAL_KEY and the series — deliberately distinguishing seed-cache unavailability/corruption from errors blamed on a healthy canonical key (per #3707 context).

Solutions

  1. Verify the seriesId exists in the seed (inspect the Redis seed key / seed-meta)
  2. Run the seed worker to (re)populate BLS_CANONICAL_KEY
  3. Check server logs for a corrupt envelope and repair the seed entry
  4. Retry after seeding; if it persists, treat the seed as unavailable and surface a 503 for this series

Example fix

// before
const data = await getBlsSeries({ seriesId: 'CUUR0000SA0' }); // seed empty -> SeedUnavailableError
// after
await runBlsSeedWorker(); // repopulate BLS_CANONICAL_KEY first
const data = await getBlsSeries({ seriesId: 'CUUR0000SA0' });
Defensive patterns

Strategy: try-catch

Validate before calling

const meta = await redis.get(`seed-meta:${BLS_CANONICAL_KEY}`);
if (!meta) throw new Error('BLS seed not populated');

Type guard

const isServable = (entry) => entry != null && typeof entry === 'object' && typeof entry.seriesId === 'string' && Array.isArray(entry.observations);

Try / catch

try { return await getBlsSeries(req); } catch (e) { if (e instanceof SeedUnavailableError) { log.warn('BLS seed unavailable', { seriesId: req.seriesId }); return respond503(); } throw e; }

Prevention

When it happens

Trigger: Requesting a seriesId absent from the seed cache; the seed Redis key holding a corrupt/unparseable envelope so isServableSeries fails for every entry; Redis seed never populated (worker down, seed job skipped).

Common situations: Typo'd or retired series ID; expired/evicted Redis seed data; seed-meta writer failing so the envelope is stale or malformed; fresh deployment before the first seed run.

Related errors


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

Appendix: source

Thrown at server/worldmonitor/economic/v1/get-bls-series.ts:70

): Promise<GetBlsSeriesResponse> {
  if (!req.seriesId) return { series: undefined };
  if (!KNOWN_SERIES_IDS.has(req.seriesId)) return { series: undefined };

  const seeded = await readRequiredSeed(BLS_CANONICAL_KEY, value => {
    const data = value as { series?: unknown } | null;
    return Array.isArray(data?.series) ? (data.series as unknown[]) : undefined;
  });

  // A known series absent from — or malformed within — a valid seed is
  // unavailable, not empty: the seeder refuses a partial cohort, so this only
  // fires on drift between the published ids and the contract, or on a
  // corrupted envelope. Name the series so the 503 log does not blame the
  // healthy canonical key.
  const series = seeded.find(
    (entry): entry is BlsSeries => isServableSeries(entry) && entry.seriesId === req.seriesId,
  );
  if (!series) {
    throw new SeedUnavailableError(`${BLS_CANONICAL_KEY} series ${req.seriesId}`);
  }

  const limit = normalizeLimit(req.limit);
  const obs = series.observations;
  const sliced = obs.length > limit ? obs.slice(-limit) : obs;

  return { series: { ...series, observations: sliced } };
}

View on GitHub (pinned to e586b8b4b8)