koala73/worldmonitor · error

Dashboard is no longer available.

Error message

Dashboard is no longer available.

What it means

applyMissionPresetForWebMcp is a WebMCP/agent entry point on EventHandlerManager that applies a bundled mission preset to the live dashboard. Before doing any work it checks this.ctx.isDestroyed; if the dashboard context has already been torn down there is no live state to mutate, so it throws 'Dashboard is no longer available.' instead of operating on a dead context. It is a lifecycle guard, not a data error.

Source

Thrown at src/app/event-handlers.ts:1282

  openMissionPresetPickerForWebMcp(): boolean {
    if (this.ctx.isDestroyed) return false;
    const mobile = this.ctx.isMobile;
    const anchor = document.getElementById(mobile ? 'mobileMenuMission' : 'missionPresetBtn');
    this.openMissionPresetPopover(anchor, mobile, 'agent');
    return this.missionPresetPopover !== null;
  }

  /**
   * WebMCP entry: apply a bundled mission preset through the same path as the
   * visible mission control. Snapshots prior dashboard state and restores it
   * if the commit throws before completion.
   */
  applyMissionPresetForWebMcp(presetId: MissionPresetId): {
    changed: boolean;
    priorPresetId: string | null;
  } {
    if (this.ctx.isDestroyed) {
      throw new Error('Dashboard is no longer available.');
    }

    const snapshot = this.snapshotMissionDashboardState();
    try {
      this.applyMissionPreset(presetId, 'agent');
      const nextPresetId = loadStoredMissionPreset()?.id ?? null;
      const mapState = this.ctx.map?.getState();
      const changed = snapshot.presetId !== nextPresetId
        || JSON.stringify(snapshot.panelSettings) !== JSON.stringify(this.ctx.panelSettings)
        || JSON.stringify(snapshot.mapLayers) !== JSON.stringify(this.ctx.mapLayers)
        || snapshot.mapView !== (mapState?.view ?? snapshot.mapView)
        || snapshot.mapZoom !== (mapState?.zoom ?? snapshot.mapZoom)
        || snapshot.timeRange !== (mapState?.timeRange ?? snapshot.timeRange);
      return { changed, priorPresetId: snapshot.presetId };
    } catch (error) {
      this.restoreMissionDashboardState(snapshot);
      throw error;
    }

View on GitHub (pinned to 9361220cc0)

Solutions

  1. Check the destroyed flag before calling: only invoke applyMissionPresetForWebMcp while the dashboard context is alive.
  2. Re-acquire a fresh dashboard/EventHandlerManager reference after navigation or reload instead of reusing a cached one.
  3. Catch this error in agent tooling and treat it as a no-op 'page gone' result rather than a preset failure, then re-attach and retry on the new instance.
  4. Debounce/queue agent commands so late-arriving preset commands are dropped once teardown begins.

Example fix

// before
const result = cachedDashboard.applyMissionPresetForWebMcp('crisis-watch');
// after
if (!cachedDashboard || cachedDashboard.ctx.isDestroyed) {
  cachedDashboard = attachDashboard(); // re-acquire after teardown
}
const result = cachedDashboard.applyMissionPresetForWebMcp('crisis-watch');
Defensive patterns

Strategy: try-catch

Validate before calling

if (dashboard && !dashboard.ctx.isDestroyed) {
  // safe to call
}

Type guard

function isDashboardAlive(d: { ctx: { isDestroyed: boolean } } | null | undefined): d is { ctx: { isDestroyed: false } } {
  return !!d && !d.ctx.isDestroyed;
}

Try / catch

try {
  const r = dashboard.applyMissionPresetForWebMcp(presetId);
  return r;
} catch (e) {
  if (e instanceof Error && e.message === 'Dashboard is no longer available.') {
    return { changed: false, priorPresetId: null }; // treat as page-gone no-op
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling dashboard.applyMissionPresetForWebMcp(presetId) after the dashboard was destroyed — e.g. an automation/MCP agent session holding a stale reference to the EventHandlerManager while the page is navigating away, hot-reloading, or the dashboard's destroy() has already run.

Common situations: MCP/agent tools cached across page reloads; single-page-app navigation that tears down the dashboard while a queued agent command still runs; dev-mode hot module replacement replacing the app instance; calling the API from a setTimeout/promise that resolves after teardown.

Related errors


AI-assisted analysis of koala73/worldmonitor@9361220cc0 (2026-09-01). Data as JSON: /api/errors/361116129ec59d66. Report an issue: GitHub.