koala73/worldmonitor · error · McpSourceUnavailableError

No hotspot-escalation input feeds are available

Error message

No hotspot-escalation input feeds are available

What it means

Thrown by requireAnyInput() inside the get_hotspot_escalation MCP tool. The tool reads five feeds (news insights, CII risk scores, military flights, unrest events, earthquakes) to compute escalation scores for the 29 curated hotspots. If all five are null, no score can be computed for any hotspot, so it throws McpSourceUnavailableError. Note that hotspot_id validation happens BEFORE the cache read, so this error only fires when the hotspot_id is valid or omitted — an unknown hotspot_id returns an error envelope, never this throw.

Source

Thrown at api/mcp/registry/analysis-tools.ts:178

    items: { type: 'string' },
    description: 'Required cache keys that were missing or unreadable; their contribution is not treated as quiet.',
  },
  failed_inputs: {
    type: 'array',
    items: { type: 'string' },
    description: 'Subset of unavailable_inputs whose Redis read failed rather than returning a genuine miss.',
  },
} as const;

type AnalysisFreshness = Awaited<ReturnType<typeof readCachesWithFreshness>>['freshness'];

function requireAnyInput(
  payloads: unknown[],
  freshness: AnalysisFreshness,
  message: string,
): void {
  if (payloads.every((value) => value === null)) {
    throw new McpSourceUnavailableError(
      message,
      freshness.unavailable_inputs,
      freshness.failed_inputs,
    );
  }
}

function resolveLimit(raw: unknown, fallback: number): number {
  if (raw === undefined || raw === null) return fallback;
  const parsed = Math.round(Number(raw));
  if (!Number.isFinite(parsed)) return fallback;
  if (parsed <= 0) return Number.POSITIVE_INFINITY;
  return parsed;
}

export const ANALYSIS_TOOLS: ToolDef[] = [
  {
    name: 'get_signal_convergence',

View on GitHub (pinned to ffec79ac33)

Solutions

  1. Verify the five seed-meta keys exist via GET /api/health: seed-meta:news:insights, seed-meta:intelligence:risk-scores, seed-meta:military:flights, seed-meta:unrest:events, seed-meta:seismology:earthquakes.
  2. Retry after a short delay — if some feeds are mid-refresh the next call may find at least one non-null payload.
  3. If the outage is isolated to one or two feeds (not all five), this error should NOT fire; investigate why readCachesWithFreshness returned null for the others too.
  4. Confirm the seeder jobs are running on schedule (Railway cron) and writing seed-meta:* markers.
Defensive patterns

Strategy: retry

Validate before calling

// Check the five hotspot feeds before calling get_hotspot_escalation
const health = await fetch('/api/health').then(r => r.json());
const feeds = ['news:insights','intelligence:risk-scores','military:flights','unrest:events','seismology:earthquakes'];
const live = feeds.filter(k => health.seedMeta?.[`seed-meta:${k}`]);
if (live.length === 0) {
  throw new Error('All hotspot-escalation feeds unseeded; retry after seeder runs');
}

Type guard

function isMcpSourceUnavailableError(e: unknown): e is { unavailableInputs: string[]; failedInputs: string[] } & Error {
  return e instanceof Error && (e as any).name === 'McpSourceUnavailableError';
}

Try / catch

try {
  const result = await callMcpTool('get_hotspot_escalation', { hotspot_id: 'ukraine' });
} catch (e) {
  if (isMcpSourceUnavailableError(e)) {
    // All five feeds null — wait for seeder and retry
    await backoffRetry(60_000);
  } else throw e;
}

Prevention

When it happens

Trigger: Calling get_hotspot_escalation (with or without hotspot_id) when news:insights:v1, intelligence:risk-scores:live, military:flights:v1, unrest:events:v1, and seismology:earthquakes:v1 are all null in Redis simultaneously. This is a total feed outage across news, risk, military, unrest, and seismology domains.

Common situations: Cold start before seeders populate the five caches; Redis flush or failover; a systemic seeder pipeline outage affecting multiple domain seed jobs at once; env misconfiguration where the edge function reads from a different (empty) Redis instance than the seeders write to.

Related errors


AI-assisted analysis of koala73/worldmonitor@ffec79ac33 (2026-08-12). Data as JSON: /api/errors/11127de37783f2ad. Report an issue: GitHub.