actualbudget/actual · error

Unrecognized menu option: ${String(item)}

Error message

Unrecognized menu option: ${String(item)}

What it means

HelpMenu's handleItemSelect switches over the selected menu item's name and dispatches the corresponding action (open URL, start tour, push modal, etc.). Any item name that reaches the default branch is not one of the known options, so the component throws 'Unrecognized menu option' to surface the programming mistake loudly rather than silently doing nothing.

Source

Thrown at packages/desktop-client/src/components/HelpMenu.tsx:106

  const handleItemSelect = (item: HelpMenuItem) => {
    switch (item) {
      case 'docs':
        openDocsForCurrentPage();
        break;
      case 'discord':
        window.Actual.openURLInBrowser('https://discord.gg/pRYNYr4W5A');
        break;
      case 'keyboard-shortcuts':
        dispatch(pushModal({ modal: { name: 'keyboard-shortcuts' } }));
        break;
      case 'start-tour':
        startTour();
        break;
      case 'goal-templates':
        dispatch(pushModal({ modal: { name: 'goal-templates' } }));
        break;
      default:
        throw new Error(`Unrecognized menu option: ${String(item)}`);
    }
  };

  useHotkeys('?', () => setMenuOpen(true), { useKey: true });

  return (
    <SpaceBetween>
      <HelpButton ref={menuButtonRef} onPress={toggleMenuOpen} />

      <Popover
        placement="bottom end"
        offset={8}
        triggerRef={menuButtonRef}
        isOpen={isMenuOpen}
        onOpenChange={() => setMenuOpen(false)}
      >
        <Menu
          onMenuSelect={(item: HelpMenuItem) => {

View on GitHub (pinned to d4334cb6e6)

Solutions

  1. Add a `case` for the new item name in handleItemSelect before dispatching.
  2. Check for typos and keep item names in the items array in sync with the switch cases.
  3. Type the menu item names as a union so TypeScript flags unhandled names at compile time.
  4. Rebuild/reload the client if a stale bundle is serving an outdated menu.
  5. If you only meant to trigger the help menu, use the '?' hotkey or a known item name (e.g. 'goal-templates').

Example fix

// before
case 'goal-templates':
  dispatch(pushModal({ modal: { name: 'goal-templates' } }));
  break;
default:
  throw new Error(`Unrecognized menu option: ${String(item)}`);
// after
case 'my-new-item':
  dispatch(openMyNewItem());
  break;
case 'goal-templates':
  dispatch(pushModal({ modal: { name: 'goal-templates' } }));
  break;
Defensive patterns

Strategy: type-guard

Validate before calling

type HelpMenuItem = 'settings-file' | 'goal-templates' | 'start-tour';
const knownItems: readonly HelpMenuItem[] = ['settings-file', 'goal-templates', 'start-tour'];
function isKnownHelpItem(item) {
  return knownItems.includes(item);
}
if (!isKnownHelpItem(item)) return; // skip dispatch

Type guard

function isHelpMenuItem(value) {
  return typeof value === 'string' && ['settings-file','goal-templates','start-tour'].includes(value);
}

Try / catch

try {
  handleItemSelect(item);
} catch (e) {
  if (e.message.startsWith('Unrecognized menu option')) {
    logger.warn('Ignoring unknown help menu item', item);
    return;
  }
  throw e;
}

Prevention

When it happens

Trigger: Adding a new item to the HelpMenu's items list (or onSelect invocation) without adding a matching case in handleItemSelect; passing an item with a changed or renamed name; a typo in the item name; a stale cached item from a plugin/extension of the menu.

Common situations: Contributing a new help menu entry and forgetting the switch case; renaming an existing item in one place only; a stale client bundle serving an outdated menu.

Related errors


AI-assisted analysis of actualbudget/actual@d4334cb6e6 (2026-08-29). Data as JSON: /api/errors/3e05304ef3fbaeca. Report an issue: GitHub.