koala73/worldmonitor · error · DashboardBindingError

map_unavailable

map_unavailable

Error message

Map is not available.

What it means

DashboardBindingError 'map_unavailable' thrown by getWebMcpDashboardContext() when ctx.map is falsy on a live (not destroyed) app. The context snapshot includes map view/center/zoom/timeRange, so it refuses rather than fabricate a map-less snapshot. Distinct from 'app_destroyed' (previous guard, line 40): the app is fine, the map renderer specifically never came up.

Source

Thrown at src/app/webmcp-dashboard.ts:43

    reason,
    message: reason === 'viewport_superseded'
      ? 'Map movement was superseded by a newer viewport action.'
      : reason === 'renderer_changed'
        ? 'Map renderer changed before the movement completed.'
        : 'Map movement was interrupted before it completed.',
    targets: result.targets.map((target) => ({ ...target, status: 'denied', reason })),
  };
}

export function getWebMcpDashboardContext(
  ctx: AppContext,
  variant: string,
): DashboardContextSnapshot {
  if (ctx.isDestroyed) {
    throw new DashboardBindingError('app_destroyed', 'Dashboard is no longer available.');
  }
  if (!ctx.map) {
    throw new DashboardBindingError('map_unavailable', 'Map is not available.');
  }

  const mapState = ctx.map.getState();
  const center = ctx.map.getCenter();

  return {
    variant,
    map: {
      view: mapState.view,
      center,
      zoom: mapState.zoom,
      timeRange: mapState.timeRange,
      enabledLayers: Object.entries(mapState.layers)
        .filter(([, enabled]) => enabled === true)
        .map(([layer]) => layer),
    },
    panels: {
      mounted: Object.keys(ctx.panels),

View on GitHub (pinned to eeab0a219f)

Solutions

  1. Wait for map initialization (or check ctx.map truthy) before requesting dashboard context
  2. If the map legitimately fails to init, check the browser console for WebGL/renderer errors and either fix the environment or treat 'map_unavailable' as a degraded-but-valid mode that omits map fields
  3. Guard tool registration: only advertise map-dependent tools when ctx.map exists

Example fix

// before
const snapshot = getWebMcpDashboardContext(ctx, variant); // throws 'Map is not available.'

// after
if (!ctx.map) {
  return { ok: false, status: 'denied', reason: 'map_unavailable' } as const;
}
const snapshot = getWebMcpDashboardContext(ctx, variant);
Defensive patterns

Strategy: type-guard

Validate before calling

if (!ctx.map) {
  return { ok: false, status: 'denied', reason: 'map_unavailable' }; // degrade gracefully instead of throwing
}

Type guard

function hasMapRenderer(ctx: AppContext): ctx is AppContext & { map: NonNullable<AppContext['map']> } {
  return !ctx.isDestroyed && ctx.map != null;
}

Try / catch

try { snapshot = getWebMcpDashboardContext(ctx, variant); } catch (e) { if (e instanceof DashboardBindingError && e.code === 'map_unavailable') snapshot = snapshotWithoutMap(variant); else throw e; }

Prevention

When it happens

Trigger: Calling get_dashboard_context before the map renderer initialized (it is created lazily), when WebGL is unavailable in the browser so map creation failed, when the map is disabled in settings or not part of the current variant, or on a headless/CI browser without GPU.

Common situations: Agent tool calls arriving during early startup before the map chunk finishes loading; browsers with WebGL blocked (hardware acceleration off, remote desktop, locked-down enterprise chrome); e2e test environments where the map panel is disabled to keep tests light.

Related errors


AI-assisted analysis of koala73/worldmonitor@eeab0a219f (2026-08-21). Data as JSON: /api/errors/8b8172bc2ffcec3c. Report an issue: GitHub.