{"record":{"id":"aa2ed1b8277b7675","repo":"koala73/worldmonitor","slug":"malformed-arguments","errorCode":"malformed_arguments","errorMessage":"Unknown mission preset: ${presetId}","messagePattern":"Unknown mission preset: (.+?)","errorType":"error_code","errorClass":"MissionPresetCatalogError","httpStatus":null,"severity":"error","filePath":"src/services/webmcp-mission-preset-catalog.ts","lineNumber":166,"sourceCode":"\nfunction unavailableReason(item: {\n  monitorCompatible: boolean;\n  entitled: boolean;\n  targetCancellationSupported?: boolean;\n}): MissionPresetUnavailableReason | undefined {\n  if (!item.monitorCompatible) return 'preset_incompatible';\n  if (!item.entitled) return 'preset_not_entitled';\n  if (item.targetCancellationSupported === false) return 'target_cancellation_unsupported';\n  return undefined;\n}\n\nexport function buildMissionPresetCatalogItem(\n  presetId: MissionPresetId,\n  live: MissionPresetCatalogLiveState,\n): MissionPresetCatalogItem {\n  const preset = getMissionPreset(presetId);\n  if (!preset) {\n    throw new MissionPresetCatalogError('malformed_arguments', `Unknown mission preset: ${presetId}`);\n  }\n\n  const matchingPanels = getMissionPresetPanelMatches(presetId, live.variant);\n  const monitorCompatible = isMissionPresetMonitorCompatible(presetId, live.variant);\n  const panelIds = monitorCompatible\n    ? preset.panels.filter((panelId) => panelId === 'map' || matchingPanels.includes(panelId))\n    : [];\n  const entitled = resolveEntitled(matchingPanels, live);\n  const reason = unavailableReason({\n    monitorCompatible,\n    entitled,\n    targetCancellationSupported: live.targetCancellationSupported,\n  });\n  const available = reason === undefined;\n\n  return {\n    id: preset.id,\n    label: preset.label,","sourceCodeStart":148,"sourceCodeEnd":184,"githubUrl":"https://github.com/koala73/worldmonitor/blob/9361220cc013571781071f0206e4d80fd14b2f7f/src/services/webmcp-mission-preset-catalog.ts#L148-L184","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Validate the presetId against the known preset registry (getMissionPreset(presetId) !== undefined or a MissionPresetId union check) before calling buildMissionPresetCatalogItem.","Import preset ids from the typed MissionPresetId union / MISSION_PRESETS keys instead of hardcoding strings.","Catch MissionPresetCatalogError and check reason === 'malformed_arguments' to return a friendly 'unknown preset' message listing valid ids.","If the id came from persisted state, migrate or clear stale preset ids after preset renames."],"exampleFix":"// before\nbuildMissionPresetCatalogItem(params.presetId as MissionPresetId, live);\n// after\nif (getMissionPreset(params.presetId) === undefined) {\n  throw new Error(`presetId '${params.presetId}' is not a known mission preset`);\n}\nconst item = buildMissionPresetCatalogItem(params.presetId, live);","handlingStrategy":"type-guard","validationCode":"import { MISSION_PRESETS } from '@/services/mission-presets';\nconst KNOWN_PRESET_IDS = new Set(Object.keys(MISSION_PRESETS));\nif (!KNOWN_PRESET_IDS.has(presetId)) {\n  throw new Error(`Unknown mission preset '${presetId}'. Valid: ${[...KNOWN_PRESET_IDS].join(', ')}`);\n}","typeGuard":"function isMissionPresetId(value: string): value is MissionPresetId {\n  return Object.prototype.hasOwnProperty.call(MISSION_PRESETS, value);\n}","tryCatchPattern":"try {\n  const item = buildMissionPresetCatalogItem(presetId, live);\n} catch (err) {\n  if (err instanceof MissionPresetCatalogError && err.reason === 'malformed_arguments') {\n    return { ok: false, error: `Unknown preset '${presetId}'` };\n  }\n  throw err;\n}","preventionTips":["Only pass ids typed as MissionPresetId; never cast raw strings.","Validate externally supplied (MCP/LLM) preset ids against the registry before use.","Migrate persisted preset ids when the MISSION_PRESETS registry changes.","List valid ids in error messages surfaced to agents so they can self-correct."],"tags":["validation","mission-presets","catalog","unknown-identifier"],"backgroundTag":"invalid-argument-value","analyzedSha":"9361220cc013571781071f0206e4d80fd14b2f7f","analyzedAt":"2026-09-01T10:32:37.851Z","contentChangedAt":"2026-09-01T10:32:37.851Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}