actualbudget/actual · error

Unrecognized menu option: ${String(name)}

Error message

Unrecognized menu option: ${String(name)}

What it means

EnvelopeIncomeBalanceMenuModal throws when the category/envelope menu's onSelect receives an option name with no case in its switch. Handled options include carryover and view; anything else is an invariant violation indicating a menu item was rendered without a corresponding handler.

Source

Thrown at packages/desktop-client/src/components/modals/EnvelopeIncomeBalanceMenuModal.tsx:120

                    textAlign: 'center',
                    ...styles.veryLargeText,
                  }}
                />
              )}
            </BalanceWithCarryover>
          </View>
          <Menu
            getItemStyle={() => defaultMenuItemStyle}
            onMenuSelect={name => {
              switch (name) {
                case 'carryover':
                  onCarryover?.(!carryover);
                  break;
                case 'view':
                  onShowActivity?.();
                  break;
                default:
                  throw new Error(`Unrecognized menu option: ${String(name)}`);
              }
            }}
            items={[
              {
                name: 'carryover',
                text: carryover
                  ? t('Disable auto hold')
                  : t('Enable auto hold'),
              },
              {
                name: 'view',
                text: t('View transactions'),
              },
            ]}
          />
        </>
      )}
    </Modal>

View on GitHub (pinned to d4334cb6e6)

Solutions

  1. Add a case for the reported name with the appropriate callback call.
  2. Ensure every object in the `items` array has a matching case in the switch (name strings must match exactly).
  3. Swap the throw for console.warn if unknown options should be ignored at runtime.
  4. Derive the union of item names as a type and make the switch exhaustive to catch this at compile time.

Example fix

// before
case 'view':
  onShowActivity?.();
  break;
default:
  throw new Error(`Unrecognized menu option: ${String(name)}`);
// after
case 'view':
  onShowActivity?.();
  break;
case 'transfer':
  onTransfer?.();
  break;
default:
  console.warn('Unrecognized menu option:', name);
Defensive patterns

Strategy: type-guard

Validate before calling

const HANDLED = new Set(['carryover', 'view']);
if (!HANDLED.has(name)) {
  console.warn('Unknown envelope menu option:', name);
  return;
}

Type guard

type EnvelopeMenuOption = 'carryover' | 'view';
function isEnvelopeMenuOption(name: string): name is EnvelopeMenuOption {
  return ['carryover', 'view'].includes(name);
}

Try / catch

try {
  onSelect(name);
} catch (err) {
  if (String(err).includes('Unrecognized menu option')) {
    console.warn('Ignoring menu option', name);
  } else {
    throw err;
  }
}

Prevention

When it happens

Trigger: Selecting an item in the envelope/income-balance context menu whose `name` isn't handled — typically after a new item is appended to the modal's `items` array (e.g. 'transfer', 'hide') without adding its case.

Common situations: Contributors adding an envelope menu action without extending the switch; renames of an existing item name string; forks injecting extra menu entries.

Related errors


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