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 reads

View on GitHub (pinned to 9361220cc0)

Solutions

  1. Retry the call after a short delay — transient nulls and stampede windows usually clear quickly
  2. Check /api/health for the market keys' freshness and seed-meta markers
  3. Verify UPSTASH_REDIS_REST_URL and UPSTASH_REDIS_REST_TOKEN on the MCP edge match the store the market producer writes
  4. 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

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


AI-assisted analysis of koala73/worldmonitor@9361220cc0 (2026-08-21). Data as JSON: /api/errors/ae9161d16590d4ba. Report an issue: GitHub.