koala73/worldmonitor · error
failed to build coverage snapshot
Error message
failed to build coverage snapshot
What it means
The Fastify route GET /worldmonitor/coverage (query market, default 'ae') returned 500 because buildCoverageSnapshot(market) threw. The builder aggregates coverage SQL through the pg pool in src/db/client.ts, so in practice the throw is almost always database-side: DATABASE_URL unset (getPool throws 'DATABASE_URL is not set'), a connection failure (5s connect timeout), or a SQL/shape error. The route logs the real cause via fastify.log.error and returns only this generic string.
Source
Thrown at consumer-prices-core/src/api/routes/worldmonitor.ts:20
import { buildCoverageSnapshot } from '../../snapshots/coverage.js';
import {
buildBasketSeriesSnapshot,
buildCategoriesSnapshot,
buildFreshnessSnapshot,
buildMoversSnapshot,
buildOverviewSnapshot,
buildRetailerSpreadSnapshot,
} from '../../snapshots/worldmonitor.js';
export async function worldmonitorRoutes(fastify: FastifyInstance) {
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));View on GitHub (pinned to eeab0a219f)
Solutions
- Check the server logs — fastify.log.error printed the underlying cause immediately before the 500
- Verify DATABASE_URL is set in the API process and points at a reachable Postgres
- If the cause is SQL/shape, reproduce by calling buildCoverageSnapshot(market) directly with the same market
- If pool exhaustion, raise the pg Pool max or batch snapshot callers
Example fix
// before — boot the API without checking the snapshot dependency
await app.listen({ port: 3000 });
// after — fail fast when the database backing the route is missing
if (!process.env.DATABASE_URL) throw new Error('DATABASE_URL is not set');
await query('SELECT 1');
await app.listen({ port: 3000 }); Defensive patterns
Strategy: retry
Validate before calling
// startup preflight for every worldmonitor snapshot route
async function snapshotDepsReady(): Promise<boolean> {
if (!process.env.DATABASE_URL) return false;
try { await query('SELECT 1'); return true; } catch { return false; }
} Try / catch
let data;
for (let attempt = 1; attempt <= 3; attempt++) {
const res = await fetch('/worldmonitor/coverage?market=ae');
if (res.ok) { data = await res.json(); break; }
if (res.status !== 500) throw new Error(`coverage: HTTP ${res.status}`);
await sleep(attempt * 1_000); // db-backed 500s are usually transient
} Prevention
- Validate DATABASE_URL and run SELECT 1 before binding the API port
- Monitor the fastify error log, not the 500 body — the body intentionally hides the cause
- Keep snapshot queries covered by tests so SQL regressions fail in CI, not in the route
When it happens
Trigger: API process started without DATABASE_URL; Postgres unreachable or credentials wrong (pool connect timeout 5000ms); a market value hitting a query path that throws; a SQL regression in buildCoverageSnapshot; pool exhaustion past max 10 connections.
Common situations: Deployed API missing its database secret; local run against a stopped Postgres; a migration renaming a column the snapshot query selects; load pushing past the 10-connection pool so queries queue and time out.
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 overview 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/29018eeec510f265.
Report an issue: GitHub.