actualbudget/actual · error
Unknown budget action type: ${String(type)}
Error message
Unknown budget action type: ${String(type)} What it means
useBudgetActions' mutation builds a server call via a switch over the budget action type; the default branch throws for any type string not in the known union. It is a developer-facing exhaustiveness error: an action type reached the hook that the switch does not handle. The mutation's onError handler then surfaces a generic notification to the user.
Source
Thrown at packages/desktop-client/src/budget/mutations.ts:896
month,
N: 12,
category: args.category,
});
return null;
case 'copy-single-last':
await send('budget/copy-single-month', {
month,
category: args.category,
});
return null;
case 'copy-until-year-end':
await send('budget/copy-until-year-end', {
month,
category: args.category,
});
return null;
default:
throw new Error(`Unknown budget action type: ${String(type)}`);
}
},
onSuccess: notification => {
if (notification) {
dispatch(
addNotification({
notification: translateBudgetTemplateNotification(notification, t),
}),
);
}
},
onError: error => {
console.error('Error applying budget action:', error);
dispatchErrorNotification(
dispatch,
t('There was an error applying the budget action. Please try again.'),
error,
);View on GitHub (pinned to d4334cb6e6)
Solutions
- Use one of the supported action types handled by the switch (e.g. 'carryover', 'copy-single-last', 'set-single-3-avg')
- Fix the typo in the action type string at the call site
- If a new action was added, add a case to the switch in useBudgetActions (packages/desktop-client/src/budget/mutations.ts) mapping it to the right 'budget/*' server call
- Check the type union definition for budget actions and ensure switch exhaustiveness (a never check in default) so this fails at compile time
Example fix
// before
default:
throw new Error(`Unknown budget action type: ${String(type)}`);
// after
default: {
const _exhaustive: never = type;
throw new Error(`Unknown budget action type: ${String(_exhaustive)}`);
} Defensive patterns
Strategy: type-guard
Validate before calling
const KNOWN_ACTIONS = ['apply-multiple-templates','carryover','copy-single-last','copy-until-year-end','reset-income-carryover','set-single-3-avg','set-single-6-avg','set-single-12-avg'] as const;
if (!KNOWN_ACTIONS.includes(type)) {
throw new Error(`Unsupported budget action: ${type}`);
} Type guard
type BudgetActionType = typeof KNOWN_ACTIONS[number];
function isBudgetActionType(t: string): t is BudgetActionType {
return (KNOWN_ACTIONS as readonly string[]).includes(t);
} Try / catch
try {
await applyBudgetAction.mutateAsync({ type, month, args });
} catch (e) {
if (e instanceof Error && e.message.startsWith('Unknown budget action type')) {
dispatch(addNotification({ notification: { type: 'error', message: 'Unsupported budget action' } }));
} else throw e;
} Prevention
- Keep the action type union and the switch in sync with a never-exhaustiveness check in default
- Centralize the list of valid action types in one exported const
- Validate action strings from budget templates against the union before dispatching
- Add unit tests covering every action type in the union
When it happens
Trigger: Calling applyBudgetAction.mutate({ type: 'some-new-action', ... }) (or dispatching a budget action through a menu/component) with a type string that is not one of the handled cases, e.g. a typo, a removed/renamed action, or a new action added to the type union without adding a switch case.
Common situations: Adding a new budget action type to the union but forgetting the switch case; typos in template/action strings from budget templates ('copy-single-last' vs 'copy-last'); stale code after refactoring action names.
Related errors
- Unrecognized menu option: ${String(item)}
- Unknown modal
- Unitialised context method called: onBudgetAction
- Unitialised context method called: onToggleSummaryCollapse
- Unitialised context method called: onBudgetAction
AI-assisted analysis of actualbudget/actual@d4334cb6e6 (2026-08-29).
Data as JSON: /api/errors/65529c7d6a70bdc1.
Report an issue: GitHub.