ionic-team/ionic-framework · error · Error
animation not registered
Error message
animation not registered
What it means
Thrown by MenuController._createAnimation() when no animation builder is registered for the requested menu `type`. The controller keeps a Map of builders; the built-in 'reveal', 'push', and 'overlay' are registered automatically. Any other type name that has not been registered via menuController.registerAnimation() triggers the throw when the menu tries to open.
Source
Thrown at core/src/utils/menu-controller/index.ts:193
};
const _setOpen = async (menu: MenuI, shouldOpen: boolean, animated: boolean, role: string): Promise<boolean> => {
if (isAnimatingSync()) {
return false;
}
if (shouldOpen) {
const openedMenu = await getOpen();
if (openedMenu && menu.el !== openedMenu) {
await openedMenu.setOpen(false, false);
}
}
return menu._setOpen(shouldOpen, animated, role);
};
const _createAnimation = (type: string, menuCmp: MenuI) => {
const animationBuilder = menuAnimations.get(type) as any; // TODO(FW-2832): type
if (!animationBuilder) {
throw new Error('animation not registered');
}
const animation = animationBuilder(menuCmp);
return animation;
};
const _getOpenSync = (): HTMLIonMenuElement | undefined => {
return find((m) => m._isOpen);
};
const getMenusSync = (): HTMLIonMenuElement[] => {
return menus.map((menu) => menu.el);
};
const isAnimatingSync = (): boolean => {
return menus.some((menu) => menu.isAnimating);
};
View on GitHub (pinned to 625f9c38ad)
Solutions
- Use one of the built-in types: 'overlay', 'reveal', or 'push'.
- If you need a custom type, call menuController.registerAnimation('myType', myBuilder) before the menu opens (e.g. in app initialization).
- Check the spelling and case of the type value against what you registered.
- If registering in a lazy bundle, eager-register a fallback or ensure the bundle loads before any menu can open.
Example fix
// before
<ion-menu type="custom-reveal"></ion-menu> <!-- never registered -->
// after
import { menuController } from '@ionic/core';
menuController.registerAnimation('custom-reveal', myRevealBuilder);
// then
<ion-menu type="custom-reveal"></ion-menu> Defensive patterns
Strategy: validation
Validate before calling
// Built-in types are registered automatically:
const BUILTIN = ['overlay','reveal','push'];
const type = BUILTIN.includes(menuType) ? menuType : 'overlay';
// or, for custom:
menuController.registerAnimation('custom', builder); // before open Type guard
function isRegisteredMenuType(name: string, registered?: Set<string>): boolean {
const defaults = ['overlay','reveal','push'];
return defaults.includes(name) || (registered?.has(name) ?? false);
} Prevention
- Register custom animations during app bootstrap, before any menu opens.
- Double-check type spelling/case against registered names.
- Prefer built-in types unless you truly need a custom animation.
When it happens
Trigger: An <ion-menu type="..."> (or config menuType) is set to a custom name that was never registered with menuController.registerAnimation(name, builder), or to a typo like 'Overlay'/'overlays'. The throw fires at open time when the menu calls menuController._createAnimation(this.type, this).
Common situations: Using a custom menu animation without first calling registerAnimation; misspelling a built-in type; setting a global config menuType to a name only registered in a lazy-loaded bundle that hasn't loaded yet; copying a type name from a tutorial that registered a custom animation you didn't include.
Related errors
- "${side}" is not a valid value for [side]. Use "start" or "e
- Invalid hour cycle "${hourCycle}"
- Invalid hour cycle "${hourCycle}"
- Hour value not found from DateTimeFormat
- Invalid hour cycle "${hourCycle}"
AI-assisted analysis of ionic-team/ionic-framework@625f9c38ad (2026-08-12).
Data as JSON: /api/errors/e3b5ded7c6740b6d.
Report an issue: GitHub.