{"record":{"id":"6d02638db9af5d41","repo":"actualbudget/actual","slug":"unrecognized-menu-option-name-6d0263","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/envelope/budgetsummary/BudgetMonthMenu.tsx","lineNumber":67,"sourceCode":"            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          case 'cleanup-goal-template':\n            onEndOfMonthCleanup();\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":49,"sourceCodeEnd":85,"githubUrl":"https://github.com/actualbudget/actual/blob/d4334cb6e6123f4d3bcea1ad6166608884c7e658/packages/desktop-client/src/components/budget/envelope/budgetsummary/BudgetMonthMenu.tsx#L49-L85","documentation":"BudgetMonthMenu renders a dropdown of budget actions (copy last month, set to zero, apply templates, etc.). Its onMenuSelect handler is a switch over the selected item's `name`; if the selected name has no case, the default branch throws `Unrecognized menu option: ${name}`. This is an internal consistency guard: the items array and the switch must stay in sync, and this crash signals they did not.","triggerScenarios":"A MenuItem whose `name` is not one of 'copy-last', 'set-zero', 'check-templates', 'overwrite-with-templates', 'cleanup-goal-template' is dispatched to onMenuSelect — e.g. a newly added menu item without a matching switch case, a plugin/custom item injected into the items list, or a stale/typo'd name string.","commonSituations":"Developers adding a new budget action to the `items` array but forgetting to add the corresponding `case` in the switch; rebasing code where a case was renamed in one place but not the other; third-party code overriding the menu items.","solutions":["Add a `case` for the missing option name in the onMenuSelect switch in BudgetMonthMenu.tsx","Fix the typo/wrong name in the menu item so it matches an existing case exactly","Make the default branch a console warning (or no-op) instead of a throw if extensibility is intended"],"exampleFix":"// before\ndefault:\n  throw new Error(`Unrecognized menu option: ${name}`);\n// after\ncase 'apply-budget-template':\n  onApplyBudgetTemplates();\n  break;\ndefault:\n  throw new Error(`Unrecognized menu option: ${name}`);","handlingStrategy":"validation","validationCode":"const KNOWN = ['copy-last','set-zero','check-templates','overwrite-with-templates','cleanup-goal-template'];\nif (!KNOWN.includes(item.name)) {\n  console.warn(`Skipping unknown budget menu option: ${item.name}`);\n  return;\n}","typeGuard":"type BudgetMenuOption = 'copy-last' | 'set-zero' | 'check-templates' | 'overwrite-with-templates' | 'cleanup-goal-template';\nfunction isBudgetMenuOption(name: string): name is BudgetMenuOption {\n  return ['copy-last','set-zero','check-templates','overwrite-with-templates','cleanup-goal-template'].includes(name);\n}","tryCatchPattern":"try {\n  renderApp();\n} catch (e) {\n  if (String(e?.message).startsWith('Unrecognized menu option')) {\n    logger.warn({ name: 'menu-option-fallback' }, 'unknown menu option ignored');\n  } else throw e;\n}","preventionTips":["Type menu item names as a union type shared by `items` and the switch so TS exhaustiveness checking catches gaps","Add an exhaustiveness check (`name satisfies never`) in the default branch during development","When adding a menu item, add the switch case in the same commit/PR","Write a unit test that dispatches every item name in the items array through onMenuSelect"],"tags":["switch-default","unhandled-menu-item","react","budget-ui"],"backgroundTag":"unrecognized-enum-value","analyzedSha":"d4334cb6e6123f4d3bcea1ad6166608884c7e658","analyzedAt":"2026-08-29T01:02:11.213Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}