{"record":{"id":"8c9591f8ad3f8b94","repo":"koala73/worldmonitor","slug":"country-brief-panel-is-not-initialised","errorCode":null,"errorMessage":"Country brief panel is not initialised","messagePattern":"Country brief panel is not initialised","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/App.ts","lineNumber":1793,"sourceCode":"  }\n\n  public async init(): Promise<void> {\n    const initStart = performance.now();\n    markLcpDebug('wm:boot:app-init-start');\n\n    // WebMCP — register synchronously before any init awaits so agent\n    // scanners (isitagentready.com, in-browser agents) find the tools on\n    // their first probe. No-op in browsers without document.modelContext.\n    // Bindings await `this.uiReady` (resolves after Phase-4 UI init) so\n    // a tool invoked during the startup window waits for the target\n    // panel to exist instead of throwing. A 10s timeout keeps a genuinely\n    // broken state from hanging the caller. Store the returned controller\n    // so destroy() can unregister every tool on teardown.\n    this.webMcpController = registerWebMcpTools({\n      openCountryBriefByCode: async (code, country) => {\n        await this.waitForUiReady();\n        if (!this.state.countryBriefPage) {\n          throw new Error('Country brief panel is not initialised');\n        }\n        await this.countryIntel.openCountryBriefByCode(code, country);\n      },\n      resolveCountryName: (code) => CountryIntelManager.resolveCountryName(code),\n      openSearch: async () => {\n        // openSearch() awaits UI readiness internally and throws on failure when\n        // throwOnFailure is set, so the agent receives a real success/failure.\n        // (Re-checking searchModal here would spuriously throw if a concurrent\n        // Cmd+K closed it between open and the check — #4403 review ADV-4.)\n        await this.openSearch({ throwOnFailure: true });\n      },\n      getDashboardContext: async () => {\n        await this.waitForDashboardReady();\n        return getWebMcpDashboardContext(this.state, SITE_VARIANT);\n      },\n      applyDashboardAction: async (action) => {\n        return runDashboardActionBinding(this.state, action, {\n          waitForUiReady: () => this.waitForDashboardReady(false),","sourceCodeStart":1775,"sourceCodeEnd":1811,"githubUrl":"https://github.com/koala73/worldmonitor/blob/eeab0a219fce0f02a00603b532dbae9041b934ac/src/App.ts#L1775-L1811","documentation":"Thrown by the WebMCP open_country_brief tool binding in App.ts. After awaiting this.waitForUiReady(), the binding requires this.state.countryBriefPage to exist; if the general UI finished initializing but the country brief page never mounted, invoking the tool throws this error rather than silently doing nothing.","triggerScenarios":"An agent (browser MCP client) calls open_country_brief during or after startup while the country brief page is disabled in panel settings, failed to mount, or is not part of this build/variant. It is NOT the startup-timeout path: waitForUiReady already resolved, so the UI as a whole is up and only this panel is missing.","commonSituations":"User disabled the country brief panel in settings before an agent session; the country-intel lazy chunk failed to load (network error) leaving the dashboard otherwise functional; a stripped-down variant that ships WebMCP tools but not every panel.","solutions":["Enable/mount the country brief page before offering open_country_brief to agents — verify state.countryBriefPage is set","Make tool registration or the tool result conditional: return a structured 'panel unavailable' result instead of throwing when this.state.countryBriefPage is falsy","If the panel should be there, check the browser console for country-intel chunk load failures and fix the underlying mount error"],"exampleFix":"// before\nopenCountryBriefByCode: async (code, country) => {\n  await this.waitForUiReady();\n  if (!this.state.countryBriefPage) throw new Error('Country brief panel is not initialised');\n  await this.countryIntel.openCountryBriefByCode(code, country);\n},\n\n// after (graceful result instead of throw):\nopenCountryBriefByCode: async (code, country) => {\n  await this.waitForUiReady();\n  if (!this.state.countryBriefPage) {\n    return { ok: false, status: 'denied', reason: 'country_brief_disabled' } as const;\n  }\n  await this.countryIntel.openCountryBriefByCode(code, country);\n  return { ok: true } as const;\n},","handlingStrategy":"try-catch","validationCode":"// In the tool host, before dispatching to the panel:\nif (!app.state.countryBriefPage) {\n  return { ok: false, status: 'denied', reason: 'country_brief_unavailable' };\n}","typeGuard":"function isCountryBriefReady(app: { state: { countryBriefPage: unknown } }): boolean {\n  return app.state.countryBriefPage != null;\n}","tryCatchPattern":"try { await openCountryBrief(code, country); } catch (e) { if (e instanceof Error && e.message === 'Country brief panel is not initialised') informAgent('country brief disabled in this session'); else throw e; }","preventionTips":["Only register/advertise the country-brief tool once the panel mounts","Keep panel enablement state in one place so tool availability and UI stay in sync","Watch for country-intel chunk load failures in console when this fires"],"tags":["webmcp","agent-tools","ui-initialisation","country-brief"],"backgroundTag":"component-not-initialised","analyzedSha":"eeab0a219fce0f02a00603b532dbae9041b934ac","analyzedAt":"2026-08-21T16:51:25.751Z","schemaVersion":2},"datasetVersion":"2026-08-23T16:17:53.355Z"}