koala73/worldmonitor · error · MissionPresetCatalogError

malformed_arguments

malformed_arguments

Error message

Unknown mission preset: ${presetId}

What it means

buildMissionPresetCatalogItem() resolves a mission preset id through getMissionPreset() before building its catalog row. If the id does not match any registered preset in the MISSION_PRESETS registry, the function throws MissionPresetCatalogError with reason 'malformed_arguments'. It guards the catalog against silently emitting rows for non-existent presets.

Source

Thrown at src/services/webmcp-mission-preset-catalog.ts:166

function unavailableReason(item: {
  monitorCompatible: boolean;
  entitled: boolean;
  targetCancellationSupported?: boolean;
}): MissionPresetUnavailableReason | undefined {
  if (!item.monitorCompatible) return 'preset_incompatible';
  if (!item.entitled) return 'preset_not_entitled';
  if (item.targetCancellationSupported === false) return 'target_cancellation_unsupported';
  return undefined;
}

export function buildMissionPresetCatalogItem(
  presetId: MissionPresetId,
  live: MissionPresetCatalogLiveState,
): MissionPresetCatalogItem {
  const preset = getMissionPreset(presetId);
  if (!preset) {
    throw new MissionPresetCatalogError('malformed_arguments', `Unknown mission preset: ${presetId}`);
  }

  const matchingPanels = getMissionPresetPanelMatches(presetId, live.variant);
  const monitorCompatible = isMissionPresetMonitorCompatible(presetId, live.variant);
  const panelIds = monitorCompatible
    ? preset.panels.filter((panelId) => panelId === 'map' || matchingPanels.includes(panelId))
    : [];
  const entitled = resolveEntitled(matchingPanels, live);
  const reason = unavailableReason({
    monitorCompatible,
    entitled,
    targetCancellationSupported: live.targetCancellationSupported,
  });
  const available = reason === undefined;

  return {
    id: preset.id,
    label: preset.label,

View on GitHub (pinned to 9361220cc0)

Solutions

  1. Validate the presetId against the known preset registry (getMissionPreset(presetId) !== undefined or a MissionPresetId union check) before calling buildMissionPresetCatalogItem.
  2. Import preset ids from the typed MissionPresetId union / MISSION_PRESETS keys instead of hardcoding strings.
  3. Catch MissionPresetCatalogError and check reason === 'malformed_arguments' to return a friendly 'unknown preset' message listing valid ids.
  4. If the id came from persisted state, migrate or clear stale preset ids after preset renames.

Example fix

// before
buildMissionPresetCatalogItem(params.presetId as MissionPresetId, live);
// after
if (getMissionPreset(params.presetId) === undefined) {
  throw new Error(`presetId '${params.presetId}' is not a known mission preset`);
}
const item = buildMissionPresetCatalogItem(params.presetId, live);
Defensive patterns

Strategy: type-guard

Validate before calling

import { MISSION_PRESETS } from '@/services/mission-presets';
const KNOWN_PRESET_IDS = new Set(Object.keys(MISSION_PRESETS));
if (!KNOWN_PRESET_IDS.has(presetId)) {
  throw new Error(`Unknown mission preset '${presetId}'. Valid: ${[...KNOWN_PRESET_IDS].join(', ')}`);
}

Type guard

function isMissionPresetId(value: string): value is MissionPresetId {
  return Object.prototype.hasOwnProperty.call(MISSION_PRESETS, value);
}

Try / catch

try {
  const item = buildMissionPresetCatalogItem(presetId, live);
} catch (err) {
  if (err instanceof MissionPresetCatalogError && err.reason === 'malformed_arguments') {
    return { ok: false, error: `Unknown preset '${presetId}'` };
  }
  throw err;
}

Prevention

When it happens

Trigger: Calling buildMissionPresetCatalogItem('nonexistent', live) (or via presets/item accessors) with a presetId string that is not a key of the MISSION_PRESETS registry — e.g. a typo, a preset removed in a refactor, or an id passed through from an external MCP tool call.

Common situations: Storing preset ids in settings/URL and replaying them after the preset was renamed or deleted; accepting an LLM/agent-supplied preset id from the webmcp mission-preset list tool without validating it; hand-typing a preset id instead of importing a typed MissionPresetId constant.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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