actualbudget/actual · error

Unrecognized menu option: ${name}

Error message

Unrecognized menu option: ${name}

What it means

ScheduledTransactionMenu throws when a scheduled-transaction menu option has no case in its onSelect switch. Known cases include post, post-today, skip, and complete; the default branch treats any other name as an internal bug and throws.

Source

Thrown at packages/desktop-client/src/components/modals/ScheduledTransactionMenuModal.tsx:143

  return (
    <Menu
      {...props}
      onMenuSelect={name => {
        switch (name) {
          case 'post':
            onPost?.(transactionId);
            break;
          case 'post-today':
            onPost?.(transactionId, true);
            break;
          case 'skip':
            onSkip?.(transactionId);
            break;
          case 'complete':
            onComplete?.(transactionId);
            break;
          default:
            throw new Error(`Unrecognized menu option: ${name}`);
        }
      }}
      items={[
        { name: 'post', text: t('Post transaction') },
        { name: 'post-today', text: t('Post transaction today') },
        ...(canBeSkipped
          ? [{ name: 'skip', text: t('Skip next scheduled date') }]
          : []),
        ...(canBeCompleted
          ? [{ name: 'complete', text: t('Mark as completed') }]
          : []),
      ]}
    />
  );
}

View on GitHub (pinned to d4334cb6e6)

Solutions

  1. Add the missing case to the onSelect switch in ScheduledTransactionMenu.
  2. Cross-check each entry in the items array against the switch cases; fix any string mismatches.
  3. Log and ignore unknown options instead of throwing if graceful degradation is preferred.
  4. Type items' names as a closed union shared by both the items array and the switch.

Example fix

// before
case 'complete':
  onComplete?.(transactionId);
  break;
default:
  throw new Error(`Unrecognized menu option: ${name}`);
// after
case 'complete':
  onComplete?.(transactionId);
  break;
case 'edit':
  onEdit?.(transactionId);
  break;
default:
  console.warn('Unrecognized menu option:', name);
Defensive patterns

Strategy: type-guard

Validate before calling

const HANDLED = new Set(['post', 'post-today', 'skip', 'complete']);
if (!HANDLED.has(name)) {
  console.warn('Unknown schedule menu option:', name);
  return;
}

Type guard

type ScheduleMenuOption = 'post' | 'post-today' | 'skip' | 'complete';
function isScheduleMenuOption(name: string): name is ScheduleMenuOption {
  return ['post', 'post-today', 'skip', 'complete'].includes(name);
}

Try / catch

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

Prevention

When it happens

Trigger: Choosing a menu item for a scheduled transaction whose `name` isn't in the switch — e.g. after adding a new option to the `items` array (like 'edit' or 'delete') without a corresponding case.

Common situations: New menu items added in a feature branch without updating onSelect; a typo in a name string between items and cases; forks/patches extending the schedule menu.

Related errors


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