koala73/worldmonitor · error · SafeWebMcpError

validation

validation

Error message

${error.message}

What it means

withInvocationLogging maps DashboardPanelCatalogError and MissionPresetCatalogError to a SafeWebMcpError with code 'validation', reusing the catalog error's own message verbatim. These catalog errors mean the requested panel/mission-preset catalog query or identifier was rejected — the arguments failed catalog-level validation before any dashboard action ran.

Source

Thrown at src/services/webmcp.ts:786

      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] : [];
  if (!Array.isArray(result.targets)) return reasons;
  for (const target of result.targets) {
    if (target && typeof target === 'object' && 'reason' in target) {

View on GitHub (pinned to 9361220cc0)

Solutions

  1. Use list_dashboard_panels / list_mission_presets first and pass ids/values straight from that response instead of hard-coding them.
  2. Match the variant/category against the catalog's accepted enum values exactly (case-sensitive).
  3. Refresh your integration against the current dashboard version if a previously working id stopped resolving.
  4. Catch this error and surface the embedded message — it already describes the exact catalog validation problem.

Example fix

// before
await tools.call('open_dashboard_panel', { id: 'panel-cpu-temp' });
// after
const { panels } = await tools.call('list_dashboard_panels', {});
const panel = panels.find((p) => p.id === 'panel-cpu-temp');
if (!panel) throw new Error('panel-cpu-temp no longer exists in catalog');
await tools.call('open_dashboard_panel', { id: panel.id });
Defensive patterns

Strategy: validation

Validate before calling

async function panelExists(tools, id) {
  const { panels } = await tools.call('list_dashboard_panels', {});
  return panels.some((p) => p.id === id);
}

Type guard

function isCatalogValidationError(e) {
  return e instanceof Error && e.name === 'WebMcpToolError' && typeof e.message === 'string';
}

Try / catch

try {
  await tools.call('open_dashboard_panel', { id });
} catch (e) {
  if (/catalog|panel/i.test(e.message)) {
    const { panels } = await tools.call('list_dashboard_panels', {});
    const match = panels.find((p) => p.id === id);
    if (match) return tools.call('open_dashboard_panel', { id: match.id });
  }
  throw e;
}

Prevention

When it happens

Trigger: list_dashboard_panels with an invalid variant/category filter value; open_dashboard_panel / set_panel_enabled with an unknown panel id; list_mission_presets / apply_mission_preset with an unknown preset id or malformed query — i.e. any call that makes the panel or mission-preset catalog throw.

Common situations: Hard-coded panel ids that were renamed or removed in a newer dashboard version; category/variant strings that don't match the catalog enum; stale tool integrations written against an older panel catalog; typos in preset names.

Related errors


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