{"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":1432,"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    // Two downstream fetches (brief + news digest for grounding).\n    _weight: 3,\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. When the news digest is serving retained (stale) content, that grounding is DROPPED and the brief is generated without it; pass allow_stale=true to ground on the retained snapshot instead. Either way the digestCoverage block reports what the grounding was.',\n    inputSchema: {\n      type: 'object',\n      properties: {","sourceCodeStart":1414,"sourceCodeEnd":1450,"githubUrl":"https://github.com/koala73/worldmonitor/blob/e586b8b4b80f595aa7ece295eec10d76f2921240/api/mcp/registry/rpc-tools.ts#L1414-L1450","documentation":"McpSourceUnavailableError thrown in get_world_brief (api/mcp/registry/rpc-tools.ts:1007): the bootstrap endpoint call succeeded but projectSeededWorldBrief rejected the insights payload. The parenthesized reason comes from the projector and is one of: malformed-snapshot (insights not a record), empty-brief, status-not-ok, no-headlines, missing-sources, malformed-sources. The error records 'news:insights:v1' as the unavailable input with no failed reads — this is a data-quality/seed problem, not a transport failure. If raw insights arrived as a JSON string that failed to parse, it is also normalized to null first.","triggerScenarios":"Calling get_world_brief when the seeded insights snapshot exists but is empty, has status != 'ok', has no headlines, or its sources array is missing/malformed (>12 entries counts as malformed). Also when insights was stored as an unparseable string.","commonSituations":"Insights producer ran but wrote an empty/brief-less snapshot (upstream news pipeline down at write time). Stale seed from before a format change. New environment seeded with a placeholder snapshot. Producer writing more than 12 source items violating the bounded contract.","solutions":["Read the reason in the message: 'status-not-ok'/'empty-brief'/'no-headlines' point at the producer writing a degenerate snapshot — re-run or fix the insights producer","Hit GET /api/infrastructure/v1/get-bootstrap-data and inspect data.insights to see the raw payload that failed projection","If insights is a string, confirm it is valid JSON — an unparseable string is normalized to null and lands here as malformed/empty","Re-seed news:insights:v1 with a well-formed snapshot once the producer is healthy"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// Pre-check the seeded brief shape via the bootstrap endpoint\nconst boot = await fetch('https://<host>/api/infrastructure/v1/get-bootstrap-data').then(r => r.json());\nconst insights = typeof boot?.data?.insights === 'string'\n  ? JSON.parse(boot.data.insights) : boot?.data?.insights;\nconst briefOk = insights?.status === 'ok' && Array.isArray(insights?.headlines) && insights.headlines.length > 0;\nif (!briefOk) defer('seeded world brief is degenerate');","typeGuard":"function isSeededBriefUnavailable(e) {\n  return e?.name === 'McpSourceUnavailableError'\n    && /Seeded world brief unavailable \\((malformed-snapshot|empty-brief|status-not-ok|no-headlines|missing-sources|malformed-sources)\\)/.test(e?.message ?? '');\n}","tryCatchPattern":"try {\n  return await client.callTool('get_world_brief', {});\n} catch (e) {\n  if (isSeededBriefUnavailable(e)) {\n    const reason = e.message.match(/\\((.*)\\)\\$/)?.[1];\n    if (reason === 'malformed-snapshot') throw e;      // producer bug — escalate, no retry\n    return retryAfter(insightsProducerCadenceMs);       // degenerate seed — next cycle may fix it\n  }\n  throw e;\n}","preventionTips":["Have the insights producer self-check status==='ok', non-empty headlines, and 1-12 sources before writing","Monitor news:insights:v1 freshness on /api/health","Parse the reason code out of the message — it selects retry vs escalate"],"tags":["mcp","rpc","world-brief","insights","seed"],"backgroundTag":"data-source-unavailable","analyzedSha":"e586b8b4b80f595aa7ece295eec10d76f2921240","analyzedAt":"2026-08-21T16:51:25.751Z","contentChangedAt":"2026-08-21T16:51:25.751Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}