koala73/worldmonitor · error
failed to build overview snapshot
Error message
failed to build overview snapshot
What it means
The Fastify route GET /worldmonitor/overview (query market, default 'ae') returned 500 because buildOverviewSnapshot(market) threw. The overview builder computes essentials/value indices, spread, coverage and freshness via the pg pool in src/db/client.ts, so the underlying throw is typically a database problem — DATABASE_URL unset, an unreachable Postgres, or a SQL/shape regression. fastify.log.error holds the real cause; the response body intentionally does not.
Source
Thrown at consumer-prices-core/src/api/routes/worldmonitor.ts:31
fastify.get('/coverage', async (request, reply) => {
const { market = 'ae' } = request.query as { market?: string };
try {
const data = await buildCoverageSnapshot(market);
return reply.send(data);
} catch (err) {
fastify.log.error(err);
return reply.status(500).send({ error: 'failed to build coverage snapshot' });
}
});
fastify.get('/overview', async (request, reply) => {
const { market = 'ae' } = request.query as { market?: string };
try {
const data = await buildOverviewSnapshot(market);
return reply.send(data);
} catch (err) {
fastify.log.error(err);
return reply.status(500).send({ error: 'failed to build overview snapshot' });
}
});
fastify.get('/movers', async (request, reply) => {
const { market = 'ae', days = '30' } = request.query as { market?: string; days?: string };
try {
const data = await buildMoversSnapshot(market, parseInt(days, 10));
return reply.send(data);
} catch (err) {
fastify.log.error(err);
return reply.status(500).send({ error: 'failed to build movers snapshot' });
}
});
fastify.get('/retailer-spread', async (request, reply) => {
const { market = 'ae', basket = 'essentials-ae' } = request.query as {
market?: string;
basket?: string;View on GitHub (pinned to eeab0a219f)
Solutions
- Read the fastify error log for the underlying exception
- Confirm DATABASE_URL and database reachability from the API host
- Check that the index computation pipeline has run for the requested market
- Reproduce with buildOverviewSnapshot(market) directly to isolate SQL vs env issues
Defensive patterns
Strategy: retry
Validate before calling
async function overviewDepsOk(): Promise<boolean> {
if (!process.env.DATABASE_URL) return false;
try { await query('SELECT 1'); return true; } catch { return false; }
}
// refuse to serve worldmonitor routes when the dependency is down Try / catch
const res = await fetch('/worldmonitor/overview?market=ae');
if (res.status === 500) {
await sleep(1_000);
return await fetch('/worldmonitor/overview?market=ae'); // one retry for transient db blips
} Prevention
- Confirm the index-computation job has produced data for the market before exposing the route
- Cache the last good overview snapshot and serve it with a staleness marker instead of erroring
- Alert on 500 spikes across all snapshot routes at once — that pattern means database, not code
When it happens
Trigger: DATABASE_URL missing in the API process; Postgres down or credentials rotated; a migration breaking the overview aggregate queries; a market code with no computed indices reaching an expectation that throws; pool exhausted at max 10.
Common situations: Fresh deployment missing the database secret; local dev against a stopped database; nightly index-computation job not having run so downstream aggregation code throws on empty input.
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 coverage snapshot
- failed to build movers snapshot
- failed to build retailer spread snapshot
- failed to build freshness snapshot
- failed to build categories snapshot
AI-assisted analysis of koala73/worldmonitor@eeab0a219f (2026-08-21).
Data as JSON: /api/errors/2be52ad774aa84d1.
Report an issue: GitHub.