{"record":{"id":"5085745485513157","repo":"actualbudget/actual","slug":"unrecognized-menu-item-name-508574","errorCode":null,"errorMessage":"Unrecognized menu item: ${name}","messagePattern":"Unrecognized menu item: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/desktop-client/src/components/modals/BudgetPageMenuModal.tsx","lineNumber":82,"sourceCode":"}: BudgetPageMenuProps) {\n  const [showHiddenCategories] = useLocalPref('budget.showHiddenCategories');\n\n  const onMenuSelect = (name: string) => {\n    switch (name) {\n      case 'add-category-group':\n        onAddCategoryGroup?.();\n        break;\n      // case 'edit-mode':\n      //   onEditMode?.(true);\n      //   break;\n      case 'toggle-hidden-categories':\n        onToggleHiddenCategories?.();\n        break;\n      case 'switch-budget-file':\n        onSwitchBudgetFile?.();\n        break;\n      default:\n        throw new Error(`Unrecognized menu item: ${name}`);\n    }\n  };\n  const { t } = useTranslation();\n\n  return (\n    <Menu\n      {...props}\n      onMenuSelect={onMenuSelect}\n      items={[\n        {\n          name: 'add-category-group',\n          text: t('Add category group'),\n        },\n        {\n          name: 'toggle-hidden-categories',\n          text: `${!showHiddenCategories ? t('Show hidden categories') : t('Hide hidden categories')}`,\n        },\n        {","sourceCodeStart":64,"sourceCodeEnd":100,"githubUrl":"https://github.com/actualbudget/actual/blob/d4334cb6e6123f4d3bcea1ad6166608884c7e658/packages/desktop-client/src/components/modals/BudgetPageMenuModal.tsx#L64-L100","documentation":"BudgetPageMenuModal's onMenuSelect throws when the selected menu item's `name` has no case in its switch. The modal enumerates known budget-page actions (e.g. toggle hidden categories, switch budget file); any unrecognized name is treated as an internal invariant violation and thrown rather than silently ignored.","triggerScenarios":"User selects a budget page menu item whose `name` string is not one of the cases handled in onMenuSelect — usually after adding a new menu item (e.g. under 'tools' or 'customize') without extending the switch.","commonSituations":"Contributors adding a new budget menu action without updating onMenuSelect; a typo or rename of an existing item's name; a fork/patch that injects extra items into the items array.","solutions":["Add the missing `case '<name>'` to onMenuSelect with the matching callback.","Verify each entry in the menu's `items` array has a corresponding case; align name strings exactly.","Replace the throw with a console.warn + early return if you want unknown items ignored in production.","Type the item names as a union so TypeScript forces the switch to stay exhaustive."],"exampleFix":"// before\ncase 'switch-budget-file':\n  onSwitchBudgetFile?.();\n  break;\ndefault:\n  throw new Error(`Unrecognized menu item: ${name}`);\n// after\ncase 'switch-budget-file':\n  onSwitchBudgetFile?.();\n  break;\ncase 'reset-cache':\n  onResetCache?.();\n  break;\ndefault:\n  console.warn('Unrecognized menu item:', name);","handlingStrategy":"type-guard","validationCode":"const KNOWN = new Set(['toggle-hidden-categories', 'switch-budget-file'] /* all cases */);\nif (!KNOWN.has(name)) {\n  console.warn('Unknown budget menu item:', name);\n  return;\n}","typeGuard":"type BudgetMenuItem = 'toggle-hidden-categories' | 'switch-budget-file';\nfunction isBudgetMenuItem(name: string): name is BudgetMenuItem {\n  return ['toggle-hidden-categories', 'switch-budget-file'].includes(name);\n}","tryCatchPattern":"try {\n  onMenuSelect(name);\n} catch (err) {\n  if (String(err).includes('Unrecognized menu item')) {\n    console.warn('Unhandled budget menu item', name);\n  } else {\n    throw err;\n  }\n}","preventionTips":["Derive the switch's case union from the same type used for items' names.","Enable exhaustive-switch checking (satisfies never in default) to catch gaps at compile time.","Add an E2E test iterating all rendered budget menu items."],"tags":["react","menu","switch-statement","developer-error"],"backgroundTag":"unhandled-switch-case","analyzedSha":"d4334cb6e6123f4d3bcea1ad6166608884c7e658","analyzedAt":"2026-08-29T01:02:11.213Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}