{"record":{"id":"ec962e3301ea4c25","repo":"koala73/worldmonitor","slug":"seeded-world-brief-unavailable-result-reason","errorCode":null,"errorMessage":"Seeded world brief unavailable (${result.reason})","messagePattern":"Seeded world brief unavailable \\((.+?)\\)","errorType":"exception","errorClass":"McpSourceUnavailableError","httpStatus":null,"severity":"error","filePath":"api/mcp/registry/rpc-tools.ts","lineNumber":911,"sourceCode":"        operation: 'bootstrap-insights',\n        tool: 'get_world_brief',\n        auth: context,\n        execution,\n      });\n      type BootstrapPayload = { data?: { insights?: unknown }; missing?: string[] };\n      const bootstrap = await insightsRes.json() as BootstrapPayload;\n      const rawInsights = bootstrap.data?.insights;\n      let insights: unknown = rawInsights;\n      if (typeof rawInsights === 'string') {\n        try {\n          insights = JSON.parse(rawInsights);\n        } catch {\n          insights = null;\n        }\n      }\n      const result = projectSeededWorldBrief(insights);\n      if ('reason' in result) {\n        throw new McpSourceUnavailableError(\n          `Seeded world brief unavailable (${result.reason})`,\n          ['news:insights:v1'],\n          [],\n        );\n      }\n      return result.value;\n    },\n    _apiPaths: ['GET /api/infrastructure/v1/get-bootstrap-data'],\n  },\n  {\n    name: 'get_country_brief',\n    _outputBudgetBytes: 65536,\n    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.',\n    inputSchema: {\n      type: 'object',\n      properties: {\n        country_code: { type: 'string', description: 'ISO 3166-1 alpha-2 country code, e.g. \"US\", \"DE\", \"CN\", \"IR\"' },\n        framework: { type: 'string', description: 'Optional analytical framework instructions to shape the analysis lens (e.g. Ray Dalio debt cycle, PMESII-PT)' },","sourceCodeStart":893,"sourceCodeEnd":929,"githubUrl":"https://github.com/koala73/worldmonitor/blob/ffec79ac339946fd2d24e85845da5755dcaa534b/api/mcp/registry/rpc-tools.ts#L893-L929","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["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.","Inspect the news:insights:v1 key in Redis and verify the worldBrief, status, topStories, and worldBriefSources fields against the gates in projectSeededWorldBrief.","Re-run the world-brief producer/seeder to regenerate a fresh, valid snapshot.","Retry after the insights seed cadence — a transient degraded snapshot is overwritten on the next cycle."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// Check that the insights snapshot is fresh and valid before calling get_world_brief\nconst health = await fetch('/api/health').then(r => r.json());\nconst insightsMeta = health.seedMeta?.['seed-meta:news:insights'];\nif (!insightsMeta || Date.now() - insightsMeta.ts > insightsMeta.maxStaleMs) {\n  throw new Error('World brief producer is stale; retry after seed cycle');\n}","typeGuard":"function isMcpSourceUnavailableError(e: unknown): e is { unavailableInputs: string[]; failedInputs: string[] } & Error {\n  return e instanceof Error && (e as any).name === 'McpSourceUnavailableError';\n}","tryCatchPattern":"try {\n  const brief = await callMcpTool('get_world_brief', {});\n} catch (e) {\n  if (isMcpSourceUnavailableError(e) && e.message.includes('Seeded world brief unavailable')) {\n    const reason = e.message.match(/\\((.*)\\)/)?.[1];\n    if (reason === 'empty-brief' || reason === 'status-not-ok') {\n      // Producer degraded — retry after seed cycle\n      await backoffRetry(120_000);\n    } else {\n      // Schema regression (malformed-sources, missing-sources) — do not retry blindly\n      logSchemaIssue(reason);\n    }\n  } else throw e;\n}","preventionTips":["Monitor the world-brief LLM producer for degraded runs (empty brief, error status).","Track the specific reason values in alerts — 'empty-brief'/'status-not-ok' need producer attention; 'malformed-*' needs schema attention.","Cache the last valid world brief as a degraded fallback during producer outages."],"tags":["mcp","source-unavailable","world-brief","validation","llm-producer"],"backgroundTag":null,"analyzedSha":"ffec79ac339946fd2d24e85845da5755dcaa534b","analyzedAt":"2026-08-12T11:24:56.012Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}