koala73/worldmonitor · error · SafeWebMcpError
unavailable
unavailable
Error message
Dashboard unavailable: ${boundedText(error.message, 160)} Reason: ${error.reason}. What it means
withInvocationLogging wraps every WorldMonitor WebMCP tool invocation. When the wrapped tool throws a DashboardUnavailableError, it is re-thrown as a SafeWebMcpError with code 'unavailable', embedding a bounded (160-char) version of the underlying error message plus the error's reason field. It signals that the dashboard SPA surface the tool needs to act on is not currently reachable, not that the tool arguments were wrong.
Source
Thrown at src/services/webmcp.ts:783
const reason = signal?.aborted
? 'cancelled'
: classifyInvocationError(error);
reportWebMcpEvent(trackEvent, 'webmcp-tool-invoked', {
tool: name,
outcome: 'failure',
reason,
});
if (signal?.aborted) throwIfWebMcpAborted(signal);
if (error instanceof SafeWebMcpError) throw error;
if (isWebMcpAbortError(error)) throw error;
if (error instanceof DashboardBindingError) {
throw new SafeWebMcpError(
`Dashboard unavailable: ${boundedText(error.message, 160)} Reason: ${error.reason}.`,
'unavailable',
);
}
if (error instanceof DashboardPanelCatalogError) {
throw new SafeWebMcpError(error.message, 'validation');
}
if (error instanceof MissionPresetCatalogError) {
throw new SafeWebMcpError(error.message, 'validation');
}
throw new SafeWebMcpError(TOOL_FAILURE_MESSAGES[name]);
}
};
}
function enforceOutputBudget(value: unknown): void {
const serialized = JSON.stringify(value);
if (typeof serialized !== 'string' || serialized.length > MAX_OUTPUT_CHARS) {
throw new SafeWebMcpError('Tool output exceeded the safe output limit.');
}
}
function structuredResultReasons(result: Record<string, unknown>): string[] {
const reasons = typeof result.reason === 'string' ? [result.reason] : [];View on GitHub (pinned to 9361220cc0)
Solutions
- Wait for the dashboard 'ready' signal (app mount/boot completion) before invoking WebMCP dashboard tools.
- Read the `Reason:` suffix in the message — it is error.reason from DashboardUnavailableError and points at the exact unavailability cause.
- Retry the tool call after a short delay if the dashboard was mid-boot; unavailability is often transient.
- If reason indicates a permanent mount failure, fix the app bootstrap (missing container, JS init error) instead of retrying the tool.
Example fix
// before
const ctx = await tools.call('get_dashboard_context');
// after
if (!dashboard.isReady()) await dashboard.whenReady();
try {
const ctx = await tools.call('get_dashboard_context');
} catch (e) {
if (e.message.includes('Dashboard unavailable')) await dashboard.whenReady();
} Defensive patterns
Strategy: retry
Validate before calling
function isDashboardReady(dashboard) {
return Boolean(dashboard && typeof dashboard.isReady === 'function' && dashboard.isReady());
} Type guard
function isDashboardUnavailableError(e) {
return e instanceof Error && e.message.startsWith('Dashboard unavailable:');
} Try / catch
try {
await tools.call('get_dashboard_context', {});
} catch (e) {
if (isDashboardUnavailableError(e)) {
await dashboard.whenReady(); // or setTimeout retry with backoff
return retry();
}
throw e;
} Prevention
- Gate all WebMCP dashboard tool calls behind the app's ready/booted signal.
- Parse the 'Reason:' suffix to distinguish transient boot from permanent mount failure.
- Use exponential backoff on retry instead of tight loops.
- Log the reason field for diagnostics before retrying.
When it happens
Trigger: Any WebMCP tool call (via `tools`) whose handler throws DashboardUnavailableError — e.g. the dashboard app instance is not mounted/initialized, or the SPA reports itself unavailable with a reason such as the page not being hydrated — at the moment the tool executes.
Common situations: Calling a dashboard tool before the WorldMonitor app finishes booting; the dashboard being torn down or navigated away; an internal app state machine marking itself unavailable with a specific reason after a failed init; embedded/iframe contexts where the SPA never mounted.
Related errors
- Dashboard is no longer available.
- app_destroyed
- app_destroyed
- Dashboard is no longer available.
- Search manager destroyed
AI-assisted analysis of koala73/worldmonitor@9361220cc0 (2026-09-01).
Data as JSON: /api/errors/011d408afe28aa75.
Report an issue: GitHub.