koala73/worldmonitor · error
failed to build basket series snapshot
Error message
failed to build basket series snapshot
What it means
The Fastify route GET /worldmonitor/basket-series returned 500 because buildBasketSeriesSnapshot(market, basket, range) threw. It is the most parameter-heavy snapshot route: market (default 'ae'), basket (default 'essentials-ae') and range (default '30d') all flow into the time-series SQL through the pg pool in src/db/client.ts. The 500 wraps a database throw (missing DATABASE_URL, unreachable Postgres, SQL regression) or an unsupported market/basket/range combination.
Source
Thrown at consumer-prices-core/src/api/routes/worldmonitor.ts:93
return reply.send(data);
} catch (err) {
fastify.log.error(err);
return reply.status(500).send({ error: 'failed to build categories snapshot' });
}
});
fastify.get('/basket-series', async (request, reply) => {
const { market = 'ae', basket = 'essentials-ae', range = '30d' } = request.query as {
market?: string;
basket?: string;
range?: string;
};
try {
const data = await buildBasketSeriesSnapshot(market, basket, range);
return reply.send(data);
} catch (err) {
fastify.log.error(err);
return reply.status(500).send({ error: 'failed to build basket series snapshot' });
}
});
}
View on GitHub (pinned to eeab0a219f)
Solutions
- Validate all three params client-side against the supported set before calling the route
- Check the fastify error log for the underlying exception
- Verify the basket slug exists for the market and has series rows
- Reproduce with buildBasketSeriesSnapshot(market, basket, range) directly
Example fix
// before — arbitrary range flows straight into the SQL layer
const data = await buildBasketSeriesSnapshot(market, basket, range);
// after — constrain params before the builder runs
const RANGES = new Set(['7d', '30d', '90d']);
if (!RANGES.has(range)) {
return reply.status(400).send({ error: `range must be one of ${[...RANGES].join(', ')}` });
}
const data = await buildBasketSeriesSnapshot(market, basket, range); Defensive patterns
Strategy: validation
Validate before calling
const VALID_RANGES = new Set(['7d', '30d', '90d']);
const VALID_BASKETS: Record<string, string[]> = { ae: ['essentials-ae'] };
if (!VALID_BASKETS[market]?.includes(basket)) throw new Error(`basket '${basket}' invalid for market '${market}'`);
if (!VALID_RANGES.has(range)) throw new Error(`range '${range}' unsupported`);
const res = await fetch(`/worldmonitor/basket-series?market=${market}&basket=${basket}&range=${range}`); Type guard
function isValidSeriesRequest(q: { market?: string; basket?: string; range?: string }): boolean {
return !!q.market
&& (VALID_BASKETS[q.market] ?? []).includes(q.basket ?? 'essentials-ae')
&& VALID_RANGES.has(q.range ?? '30d');
} Try / catch
try {
const res = await fetch(`/worldmonitor/basket-series?market=${market}&basket=${basket}&range=${range}`);
if (!res.ok) throw new Error(`basket-series: HTTP ${res.status}`);
return await res.json();
} catch (err) {
if (/HTTP 500/.test(String(err))) return readCachedSeries(market, basket, range); // last good series
throw err;
} Prevention
- Validate all three params (market, basket, range) against supported sets before the request
- Cache series snapshots — time-series data tolerates staleness well during backend incidents
- Ensure the basket-series computation job has run for a market before its routes go live
When it happens
Trigger: DATABASE_URL unset or Postgres unreachable; a basket slug with no series data for the market; a range value the series date-bucketing cannot parse; a migration breaking the series query.
Common situations: Clients composing arbitrary range strings ('6m', 'ytd') the builder never supported; deployment missing the DB secret; the basket series job not having run for a new market.
Understand the failure class
Background: Database query failed: Internal Server Error 500s wrapping SQL, Prisma, and connection failures — what to check first — this error's family across 16 libraries.
Related errors
- failed to build movers snapshot
- failed to build coverage snapshot
- failed to build overview snapshot
- failed to build retailer spread snapshot
- failed to build freshness snapshot
AI-assisted analysis of koala73/worldmonitor@eeab0a219f (2026-08-21).
Data as JSON: /api/errors/9025ee2a0d88a70e.
Report an issue: GitHub.