actualbudget/actual · error

Unrecognized menu option: ${name}

Error message

Unrecognized menu option: ${name}

What it means

BudgetMonthMenu's onSelect switch throws when the selected menu item's name does not match any of its known options (copy-last, set-zero, copy-3-avg, etc., plus the template actions like apply-goal-template / overwrite-goal-template). Like BudgetMenu, it's an invariant guard that the items list and the selection handler stay in sync.

Source

Thrown at packages/desktop-client/src/components/budget/tracking/budgetsummary/BudgetMonthMenu.tsx:62

            onSetMonthsAverage(3);
            break;
          case 'set-6-avg':
            onSetMonthsAverage(6);
            break;
          case 'set-12-avg':
            onSetMonthsAverage(12);
            break;
          case 'check-templates':
            onCheckTemplates();
            break;
          case 'apply-goal-template':
            onApplyBudgetTemplates();
            break;
          case 'overwrite-goal-template':
            onOverwriteWithBudgetTemplates();
            break;
          default:
            throw new Error(`Unrecognized menu option: ${name}`);
        }
      }}
      items={[
        { name: 'copy-last', text: t("Copy last month's budget") },
        { name: 'set-zero', text: t('Set budgets to zero') },
        {
          name: 'set-3-avg',
          text: t('Set budgets to 3 month average'),
        },
        {
          name: 'set-6-avg',
          text: t('Set budgets to 6 month average'),
        },
        {
          name: 'set-12-avg',
          text: t('Set budgets to 12 month average'),
        },
        ...(isGoalTemplatesEnabled

View on GitHub (pinned to d4334cb6e6)

Solutions

  1. Add the missing `case '<name>'` in the onSelect switch at packages/desktop-client/src/components/budget/tracking/budgetsummary/BudgetMonthMenu.tsx (around line 62).
  2. Align the item's `name` in the `items` array with an existing case string.
  3. Downgrade the default branch to a warning log instead of throwing so the month menu can't crash the budget page.

Example fix

// before
case 'overwrite-goal-template':
  onOverwriteWithBudgetTemplates();
  break;
default:
  throw new Error(`Unrecognized menu option: ${name}`);

// after
case 'overwrite-goal-template':
  onOverwriteWithBudgetTemplates();
  break;
case 'apply-goal-template':
  onApplyBudgetTemplates();
  break;
default:
  console.warn(`Unrecognized menu option: ${name}`);
Defensive patterns

Strategy: validation

Validate before calling

const KNOWN_OPTIONS = ['copy-last','set-zero','copy-3-avg','copy-6-avg','copy-12-avg','apply-goal-template','overwrite-goal-template'];
const safeItems = items.filter(item => KNOWN_OPTIONS.includes(item.name));

Type guard

function isMonthMenuOption(name: string): name is 'copy-last' | 'set-zero' | 'copy-3-avg' | 'copy-6-avg' | 'copy-12-avg' | 'apply-goal-template' | 'overwrite-goal-template' {
  return ['copy-last','set-zero','copy-3-avg','copy-6-avg','copy-12-avg','apply-goal-template','overwrite-goal-template'].includes(name);
}

Try / catch

try {
  handleSelect(name);
} catch (err) {
  if (err instanceof Error && err.message.startsWith('Unrecognized menu option')) {
    logger.warn(`Skipping unknown month menu option: ${name}`);
  } else {
    throw err;
  }
}

Prevention

When it happens

Trigger: Selecting a month-menu option whose `name` is not handled in the switch — e.g. a caller adds a custom item to the menu, or a feature flag gates an item (like 'apply-goal-template') whose case was removed/renamed, then the user clicks it.

Common situations: Feature-flag mismatch: item shown under goalTemplatesEnabled while its case lives behind a differently-named branch; plugin/fork injecting extra options; renaming item names during refactor while older UI code (or saved shortcuts) still sends the old name.

Related errors


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