{"record":{"id":"a26795b279648053","repo":"actualbudget/actual","slug":"unrecognized-menu-option-name-a26795","errorCode":null,"errorMessage":"Unrecognized menu option: ${name}","messagePattern":"Unrecognized menu option: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/desktop-client/src/components/budget/tracking/budgetsummary/BudgetMonthMenu.tsx","lineNumber":62,"sourceCode":"            onSetMonthsAverage(3);\n            break;\n          case 'set-6-avg':\n            onSetMonthsAverage(6);\n            break;\n          case 'set-12-avg':\n            onSetMonthsAverage(12);\n            break;\n          case 'check-templates':\n            onCheckTemplates();\n            break;\n          case 'apply-goal-template':\n            onApplyBudgetTemplates();\n            break;\n          case 'overwrite-goal-template':\n            onOverwriteWithBudgetTemplates();\n            break;\n          default:\n            throw new Error(`Unrecognized menu option: ${name}`);\n        }\n      }}\n      items={[\n        { name: 'copy-last', text: t(\"Copy last month's budget\") },\n        { name: 'set-zero', text: t('Set budgets to zero') },\n        {\n          name: 'set-3-avg',\n          text: t('Set budgets to 3 month average'),\n        },\n        {\n          name: 'set-6-avg',\n          text: t('Set budgets to 6 month average'),\n        },\n        {\n          name: 'set-12-avg',\n          text: t('Set budgets to 12 month average'),\n        },\n        ...(isGoalTemplatesEnabled","sourceCodeStart":44,"sourceCodeEnd":80,"githubUrl":"https://github.com/actualbudget/actual/blob/d4334cb6e6123f4d3bcea1ad6166608884c7e658/packages/desktop-client/src/components/budget/tracking/budgetsummary/BudgetMonthMenu.tsx#L44-L80","documentation":"BudgetMonthMenu's onSelect switch throws when the selected menu item's name does not match any of its known options (copy-last, set-zero, copy-3-avg, etc., plus the template actions like apply-goal-template / overwrite-goal-template). Like BudgetMenu, it's an invariant guard that the items list and the selection handler stay in sync.","triggerScenarios":"Selecting a month-menu option whose `name` is not handled in the switch — e.g. a caller adds a custom item to the menu, or a feature flag gates an item (like 'apply-goal-template') whose case was removed/renamed, then the user clicks it.","commonSituations":"Feature-flag mismatch: item shown under goalTemplatesEnabled while its case lives behind a differently-named branch; plugin/fork injecting extra options; renaming item names during refactor while older UI code (or saved shortcuts) still sends the old name.","solutions":["Add the missing `case '<name>'` in the onSelect switch at packages/desktop-client/src/components/budget/tracking/budgetsummary/BudgetMonthMenu.tsx (around line 62).","Align the item's `name` in the `items` array with an existing case string.","Downgrade the default branch to a warning log instead of throwing so the month menu can't crash the budget page."],"exampleFix":"// before\ncase 'overwrite-goal-template':\n  onOverwriteWithBudgetTemplates();\n  break;\ndefault:\n  throw new Error(`Unrecognized menu option: ${name}`);\n\n// after\ncase 'overwrite-goal-template':\n  onOverwriteWithBudgetTemplates();\n  break;\ncase 'apply-goal-template':\n  onApplyBudgetTemplates();\n  break;\ndefault:\n  console.warn(`Unrecognized menu option: ${name}`);","handlingStrategy":"validation","validationCode":"const KNOWN_OPTIONS = ['copy-last','set-zero','copy-3-avg','copy-6-avg','copy-12-avg','apply-goal-template','overwrite-goal-template'];\nconst safeItems = items.filter(item => KNOWN_OPTIONS.includes(item.name));","typeGuard":"function isMonthMenuOption(name: string): name is 'copy-last' | 'set-zero' | 'copy-3-avg' | 'copy-6-avg' | 'copy-12-avg' | 'apply-goal-template' | 'overwrite-goal-template' {\n  return ['copy-last','set-zero','copy-3-avg','copy-6-avg','copy-12-avg','apply-goal-template','overwrite-goal-template'].includes(name);\n}","tryCatchPattern":"try {\n  handleSelect(name);\n} catch (err) {\n  if (err instanceof Error && err.message.startsWith('Unrecognized menu option')) {\n    logger.warn(`Skipping unknown month menu option: ${name}`);\n  } else {\n    throw err;\n  }\n}","preventionTips":["Use a single string-literal union type for option names shared between items and onSelect.","Keep feature-flag-gated items and their switch cases adjacent so removals stay in sync.","Wrap the switch in a Record<name, handler> map for exhaustiveness checking."],"tags":["react","menu","unhandled-switch-case","ui-crash"],"backgroundTag":"unrecognized-enum-value","analyzedSha":"d4334cb6e6123f4d3bcea1ad6166608884c7e658","analyzedAt":"2026-08-29T01:02:11.213Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}