{"record":{"id":"98217f3517804da4","repo":"actualbudget/actual","slug":"unrecognized-menu-option-name-98217f","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/mobile/budget/CategoryGroupActionMenu.tsx","lineNumber":31,"sourceCode":"  onApplyBudgetTemplatesInGroup: () => void;\n};\nexport function CategoryGroupActionMenu({\n  onApplyBudgetTemplatesInGroup,\n  ...props\n}: CategoryGroupActionMenuProps) {\n  const { t } = useTranslation();\n\n  const isGoalTemplatesEnabled = useFeatureFlag('goalTemplatesEnabled');\n  return (\n    <Menu\n      {...props}\n      onMenuSelect={name => {\n        switch (name) {\n          case 'apply-budget-templates-in-group':\n            onApplyBudgetTemplatesInGroup();\n            break;\n          default:\n            throw new Error(`Unrecognized menu option: ${name}`);\n        }\n      }}\n      items={[\n        ...(isGoalTemplatesEnabled\n          ? [\n              {\n                name: 'apply-budget-templates-in-group',\n                text: t('Overwrite with templates'),\n              },\n            ]\n          : []),\n      ]}\n    />\n  );\n}\n","sourceCodeStart":13,"sourceCodeEnd":47,"githubUrl":"https://github.com/actualbudget/actual/blob/d4334cb6e6123f4d3bcea1ad6166608884c7e658/packages/desktop-client/src/components/mobile/budget/CategoryGroupActionMenu.tsx#L13-L47","documentation":"CategoryGroupActionMenu maps its menu selection callback through a switch and throws when the selected `name` does not match any known case. This is an internal exhaustiveness guard: the Menu component emitted an option ID the action menu does not handle. It usually means the items list and the switch handler are out of sync.","triggerScenarios":"`onMenuSelect` receives a menu option name not present in the switch (currently only 'apply-budget-templates-in-group' is handled) — e.g. after a new item is added to `items` without a matching case, or a stale/foreign option ID is dispatched.","commonSituations":"A developer adds a new menu item to `items` (or a feature flag reveals an item) but forgets to add the corresponding switch case; plugin or shortcut code dispatching an old option name after a rename.","solutions":["Add a switch case for the unrecognized option name in onMenuSelect.","Verify items[] entries and switch cases are kept in sync (a single source of truth for option IDs helps).","Rebuild/reload the client so the menu component and handler come from the same version.","Log the incoming name before the default case during development to catch mismatches early."],"exampleFix":"// before\ndefault:\n  throw new Error(`Unrecognized menu option: ${name}`);\n// after\ncase 'new-option':\n  onNewOption();\n  break;\ndefault: {\n  const exhaustive: never = name;\n  throw new Error(`Unrecognized menu option: ${String(exhaustive)}`);\n}","handlingStrategy":"validation","validationCode":"const HANDLED = new Set(['apply-budget-templates-in-group']);\nif (!HANDLED.has(name)) {\n  console.warn(`Ignoring unknown menu option: ${name}`);\n  return;\n}","typeGuard":"type MenuOption = 'apply-budget-templates-in-group';\nfunction isMenuOption(name: string): name is MenuOption {\n  return name === 'apply-budget-templates-in-group';\n}","tryCatchPattern":"try {\n  onMenuSelect(name);\n} catch (err) {\n  if (String(err).startsWith('Unrecognized menu option')) {\n    console.warn(`Unknown menu option: ${name}`);\n  } else {\n    throw err;\n  }\n}","preventionTips":["Derive switch cases and items[] from a single shared option-ID union type.","Use a `never` exhaustiveness check in the default case.","Add a case whenever a new menu item is added behind a feature flag.","Test menu handlers with feature flags both on and off."],"tags":["ui","menu","exhaustiveness","internal-error"],"backgroundTag":"unhandled-switch-case","analyzedSha":"d4334cb6e6123f4d3bcea1ad6166608884c7e658","analyzedAt":"2026-08-29T01:02:11.213Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}