koala73/worldmonitor · error · McpSourceUnavailableError

Seeded world brief unavailable (${result.reason})

Error message

Seeded world brief unavailable (${result.reason})

What it means

Thrown by the get_world_brief MCP tool when projectSeededWorldBrief() rejected the insights payload with a bounded reason string. The function runs a chain of validation gates on the seeded world-brief snapshot (news:insights:v1): snapshot shape, non-empty brief text, status==='ok', at least one headline, 1-12 source records, and valid source URLs. The reason names WHICH gate fired, so 'empty-brief' (stale producer) and 'malformed-sources' (schema regression) need opposite responses. The error is an McpSourceUnavailableError with news:insights:v1 as the unavailable input.

Source

Thrown at api/mcp/registry/rpc-tools.ts:911

        operation: 'bootstrap-insights',
        tool: 'get_world_brief',
        auth: context,
        execution,
      });
      type BootstrapPayload = { data?: { insights?: unknown }; missing?: string[] };
      const bootstrap = await insightsRes.json() as BootstrapPayload;
      const rawInsights = bootstrap.data?.insights;
      let insights: unknown = rawInsights;
      if (typeof rawInsights === 'string') {
        try {
          insights = JSON.parse(rawInsights);
        } catch {
          insights = null;
        }
      }
      const result = projectSeededWorldBrief(insights);
      if ('reason' in result) {
        throw new McpSourceUnavailableError(
          `Seeded world brief unavailable (${result.reason})`,
          ['news:insights:v1'],
          [],
        );
      }
      return result.value;
    },
    _apiPaths: ['GET /api/infrastructure/v1/get-bootstrap-data'],
  },
  {
    name: 'get_country_brief',
    _outputBudgetBytes: 65536,
    description: 'AI-generated per-country intelligence brief. Produces an LLM-analyzed geopolitical and economic assessment for the given country. Supports analytical frameworks for structured lenses. Returns groundingStories alongside sources: the digest articles used to ground the brief, each with corroborationCount, mentionCount, and lifecycle storyPhase, so an agent can weigh how well-corroborated the underlying reporting is.',
    inputSchema: {
      type: 'object',
      properties: {
        country_code: { type: 'string', description: 'ISO 3166-1 alpha-2 country code, e.g. "US", "DE", "CN", "IR"' },
        framework: { type: 'string', description: 'Optional analytical framework instructions to shape the analysis lens (e.g. Ray Dalio debt cycle, PMESII-PT)' },

View on GitHub (pinned to ffec79ac33)

Solutions

  1. Read the reason from the error message (inside the parentheses) — it identifies the exact gate: 'empty-brief' and 'status-not-ok' point to a producer/LLM issue; 'missing-sources'/'malformed-sources' point to a source-extraction issue; 'no-headlines' points to a topStories issue.
  2. Inspect the news:insights:v1 key in Redis and verify the worldBrief, status, topStories, and worldBriefSources fields against the gates in projectSeededWorldBrief.
  3. Re-run the world-brief producer/seeder to regenerate a fresh, valid snapshot.
  4. Retry after the insights seed cadence — a transient degraded snapshot is overwritten on the next cycle.
Defensive patterns

Strategy: retry

Validate before calling

// Check that the insights snapshot is fresh and valid before calling get_world_brief
const health = await fetch('/api/health').then(r => r.json());
const insightsMeta = health.seedMeta?.['seed-meta:news:insights'];
if (!insightsMeta || Date.now() - insightsMeta.ts > insightsMeta.maxStaleMs) {
  throw new Error('World brief producer is stale; retry after seed cycle');
}

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 brief = await callMcpTool('get_world_brief', {});
} catch (e) {
  if (isMcpSourceUnavailableError(e) && e.message.includes('Seeded world brief unavailable')) {
    const reason = e.message.match(/\((.*)\)/)?.[1];
    if (reason === 'empty-brief' || reason === 'status-not-ok') {
      // Producer degraded — retry after seed cycle
      await backoffRetry(120_000);
    } else {
      // Schema regression (malformed-sources, missing-sources) — do not retry blindly
      logSchemaIssue(reason);
    }
  } else throw e;
}

Prevention

When it happens

Trigger: Calling get_world_brief when the insights seeder produced a payload that fails one of the gates: reason='empty-brief' (worldBrief string is blank), 'status-not-ok' (producer set status to an error value), 'no-headlines' (topStories empty), 'missing-sources' (worldBriefSources absent, empty, or >12), 'malformed-sources' (sources lack any valid URL), 'malformed-snapshot' (raw is not a record), or a snapshotRejection reason (staleness/shape failure from insightsSnapshotRejection).

Common situations: The world-brief LLM producer ran but wrote a degraded snapshot (empty brief text, error status); a producer deploy changed the snapshot shape; the brief was generated but source extraction failed leaving zero usable citations; staleness — the snapshot is older than the producer's acceptance window.

Related errors


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