koala73/worldmonitor · error
cache_all_null
Error message
cache_all_null
What it means
Error 'cache_all_null' thrown in a market-snapshot cache tool (api/mcp/registry/rpc-tools.ts:1562): after Promise.all over the tool's data keys (overview/categories/movers via readJsonFromUpstash), every data read returned null/undefined. This is explicit F6 contract parity with the cache-tool path in dispatch.ts (~line 1139): an all-null data set is a degenerate-empty response (Redis transient, stampede, or pre-seed), thrown so dispatchToolsCall reports a normal tool-execution failure. It runs after the tool executed, so a Pro caller's reserved slot stays charged.
Source
Thrown at api/mcp/registry/rpc-tools.ts:2313
{ key: `seed-meta:consumer-prices:categories:${code}:30d`, maxStaleMin: 1500 },
{ key: `seed-meta:consumer-prices:movers:${code}:30d`, maxStaleMin: 1500 },
{ key: `seed-meta:consumer-prices:spread:${code}`, maxStaleMin: 1500 }, // producer's actual key shape
{ key: `seed-meta:consumer-prices:freshness:${code}`, maxStaleMin: 1500 },
];
const [dataResults, metaResults] = await Promise.all([
Promise.all(dataKeys.map((k) => readJsonFromUpstash(k))),
Promise.all(freshnessChecks.map((c) => readJsonFromUpstash(c.key))),
]);
// F6 contract parity with the cache-tool path (executeTool, ~line 1139):
// if every data read is null/undefined, this is a degenerate-empty
// response (Redis transient / stampede / pre-seed). Throw so
// dispatchToolsCall reports a normal tool-execution failure. For Pro
// callers the already-reserved slot stays charged because the tool has
// executed.
if (dataResults.every((v: unknown) => v === null || v === undefined)) {
throw new Error('cache_all_null');
}
const { cached_at, stale } = evaluateFreshness(freshnessChecks, metaResults);
return {
cached_at,
stale,
country_code: code,
data: {
overview: dataResults[0],
categories: dataResults[1],
movers: dataResults[2],
retailerSpread: dataResults[3],
freshness: dataResults[4],
},
};
},
// Hybrid tool covers the consumer-prices domain via direct Redis readsView on GitHub (pinned to 9361220cc0)
Solutions
- Retry the call after a short delay — transient nulls and stampede windows usually clear quickly
- Check /api/health for the market keys' freshness and seed-meta markers
- Verify UPSTASH_REDIS_REST_URL and UPSTASH_REDIS_REST_TOKEN on the MCP edge match the store the market producer writes
- If keys are absent, run the market seed scripts (they must write seed-meta:<key>) or wait for the producer cycle
Defensive patterns
Strategy: retry
Validate before calling
// Pre-check market dataset freshness before the call
const health = await fetch('https://<host>/api/health').then(r => r.json());
if (!health?.datasets?.['market:overview']?.fresh) defer('market cache not seeded/fresh'); Type guard
function isCacheAllNull(e) {
return e instanceof Error && e.message === 'cache_all_null';
} Try / catch
async function getMarketSnapshot(code, attempts = 3) {
for (let i = 0; i < attempts; i++) {
try { return await client.callTool(marketTool, { country_code: code }); }
catch (e) {
if (isCacheAllNull(e) && i < attempts - 1) {
await sleep(400 * 2 ** i + Math.random() * 200);
continue;
}
throw e;
}
}
} Prevention
- Confirm market seeds exist (seed-meta markers) in every new environment before enabling consumers
- Verify UPSTASH_REDIS_REST_URL/TOKEN are identical across producer and MCP edge configs
- After bumping cache-key versions, coordinate readers so they do not read the old, evicted namespace
When it happens
Trigger: Calling the market overview tool while all market cache keys are null: market data seeds never ran in this environment, Upstash is degraded/rate-limiting so reads resolve null, keys were evicted/TTL-expired between producer runs, or the MCP edge points at a different Upstash database than the market producers.
Common situations: Fresh deployment without market seeds. Upstash outage window or quota exhaustion. Region mismatch in UPSTASH_REDIS_REST_URL/TOKEN between surfaces. Key-namespace drift after a cache-key version bump (v1 → v2) with old readers.
Related errors
- cache_all_null
- Failed to enqueue scenario job
- Redis not configured
- Redis HTTP ${resp.status}
- Redis EVAL failed: ${data.error}
AI-assisted analysis of koala73/worldmonitor@9361220cc0 (2026-08-21).
Data as JSON: /api/errors/ae9161d16590d4ba.
Report an issue: GitHub.