actualbudget/actual · error
Unrecognized menu option: ${name}
Error message
Unrecognized menu option: ${name} What it means
ToBudgetMenu's onMenuSelect switch handles options like resetting the hold buffer and disabling the auto-buffer; any selected item name without a matching case hits the default branch, which throws `Unrecognized menu option: ${name}`. Like BudgetMonthMenu, it enforces that every entry in the (possibly computed) items list has a handler.
Source
Thrown at packages/desktop-client/src/components/budget/envelope/budgetsummary/ToBudgetMenu.tsx:103
switch (name) {
case 'transfer':
onTransfer?.();
break;
case 'cover':
onCover?.();
break;
case 'buffer':
onHoldBuffer?.();
onBudgetAction?.(month, 'reset-income-carryover', {});
break;
case 'reset-buffer':
onResetHoldBuffer?.();
break;
case 'disable-auto-buffer':
onBudgetAction?.(month, 'reset-income-carryover', {});
break;
default:
throw new Error(`Unrecognized menu option: ${name}`);
}
}}
items={
items.length > 0
? items
: [
{
name: 'none',
text: t('No actions available'),
disabled: true,
},
]
}
/>
);
}
View on GitHub (pinned to d4334cb6e6)
Solutions
- Add the missing `case` to the onMenuSelect switch in ToBudgetMenu.tsx
- Align the item's `name` string with an existing case (fix typos/renames)
- Log and ignore unknown options in the default branch if dynamic items must be supported
Example fix
// before
default:
throw new Error(`Unrecognized menu option: ${name}`);
// after
case 'reset-hold-buffer':
onResetHoldBuffer?.();
break;
default:
console.warn(`Unrecognized menu option: ${name}`); Defensive patterns
Strategy: validation
Validate before calling
const KNOWN_TO_BUDGET_OPTIONS = ['reset-hold-buffer','disable-auto-buffer'];
items.filter(i => !KNOWN_TO_BUDGET_OPTIONS.includes(i.name))
.forEach(i => console.warn(`Dropping unhandled ToBudgetMenu item: ${i.name}`)); Type guard
type ToBudgetMenuOption = 'reset-hold-buffer' | 'disable-auto-buffer';
function isToBudgetOption(name: string): name is ToBudgetMenuOption {
return name === 'reset-hold-buffer' || name === 'disable-auto-buffer';
} Try / catch
onMenuSelect={name => {
try {
handleOption(name);
} catch (e) {
if (String(e?.message).startsWith('Unrecognized menu option')) return;
throw e;
}
}} Prevention
- Derive the switch cases and the items array from a single typed registry of actions
- Enable TS exhaustive switch checking on the option union type
- Test every item name in both item branches (custom items and fallback list)
- Prefer warn-and-ignore over throw for menu options that may come from external sources
When it happens
Trigger: A menu item name not among the implemented cases ('reset-hold-buffer', 'disable-auto-buffer', etc.) is selected — a new/renamed item added to `items` (including the conditional `items.length > 0 ? items : [...]` branch) without a switch case, or an externally supplied item.
Common situations: Adding a new ToBudget action and missing the handler; renaming a case but not the item; passing custom items via props with names the switch doesn't know.
Related errors
- Unrecognized menu option: ${name}
- Unrecognized menu option: ${String(name)}
- InitialFocus expects a single valid React element as its chi
- Unknown budget action type: ${String(type)}
- Unknown display type: ${String(type satisfies never)}
AI-assisted analysis of actualbudget/actual@d4334cb6e6 (2026-08-29).
Data as JSON: /api/errors/d8b85c2c2804001e.
Report an issue: GitHub.