ionic-team/ionic-framework · error · Error
IonTabs cannot contain an IonRouterOutlet and an IonTab at t
Error message
IonTabs cannot contain an IonRouterOutlet and an IonTab at the same time
What it means
Thrown during React `<IonTabs>` render when children contain BOTH an `IonRouterOutlet` (by type or `isRouterOutlet`) and an `IonTab`. The two are mutually exclusive navigation models; the component rejects the combination to avoid ambiguous tab state and broken routing.
Source
Thrown at packages/react/src/components/navigation/IonTabs.tsx:181
onIonTabsDidChange,
};
}
if (onIonTabsWillChange !== undefined) {
childProps = {
...childProps,
onIonTabsWillChange,
};
}
this.ionTabContextState.tabBarProps = childProps;
});
if (!outlet && !hasTab) {
throw new Error('IonTabs must contain an IonRouterOutlet or an IonTab');
}
if (outlet && hasTab) {
throw new Error('IonTabs cannot contain an IonRouterOutlet and an IonTab at the same time');
}
if (hasTab) {
return <IonTabsInner {...this.props}></IonTabsInner>;
}
/**
* TODO(ROU-11051)
*
* There is no error handling for the case where there
* is no associated Route for the given IonTabButton.
*
* More investigation is needed to determine how to
* handle this to prevent any overwriting of the
* IonTabButton's onClick handler and how the routing
* is handled.
*/
View on GitHub (pinned to 625f9c38ad)
Solutions
- Choose one model: keep `<IonRouterOutlet>` and remove all `<IonTab>` children, or keep `<IonTab>` children and remove the outlet.
- Search the `<IonTabs>` subtree for `IonRouterOutlet` and `IonTab` and remove the unwanted one.
- For router-less tabs use `<IonTab>` + `<IonTabBar>` without an outlet.
- For router tabs use `<IonRouterOutlet>` + `<Route>` and do not declare `<IonTab>` elements.
Example fix
// before (both present)
<IonTabs>
<IonRouterOutlet><Route path="/home" component={Home} /></IonRouterOutlet>
<IonTab tab="home"><Home /></IonTab>
</IonTabs>
// after (router model only)
<IonTabs>
<IonRouterOutlet><Route path="/home" component={Home} /></IonRouterOutlet>
<IonTabBar slot="bottom"><IonTabButton tab="home" href="/home"><IonLabel>Home</IonLabel></IonTabButton></IonTabBar>
</IonTabs> Defensive patterns
Strategy: validation
Validate before calling
let outlet = false, hasTab = false;
React.Children.forEach(children, (child: any) => {
if (child?.type === IonRouterOutlet || child?.type?.isRouterOutlet) outlet = true;
else if (child?.type === IonTab) hasTab = true;
});
if (outlet && hasTab) {
throw new Error('Choose one: IonRouterOutlet (router tabs) OR IonTab (router-less tabs).');
} Type guard
function isExclusiveTabsModel(children: React.ReactNode): boolean {
let outlet = false, hasTab = false;
React.Children.forEach(children, (child: any) => {
if (child?.type === IonRouterOutlet || child?.type?.isRouterOutlet) outlet = true;
else if (child?.type === IonTab) hasTab = true;
});
return outlet !== hasTab;
} Prevention
- Pick one tabs navigation model and remove the other shape during migration.
- Review tab templates for stray IonTab or IonRouterOutlet elements.
- Keep router-less and router tab examples separate to avoid mixing.
When it happens
Trigger: Authoring `<IonTabs>` with both `<IonRouterOutlet>` and one or more `<IonTab>` components among the children (directly or inside a fragment whose first child is an outlet).
Common situations: Mid-migration between router-less and router-based tabs leaving both shapes in place; copy-pasting tab snippets that mix patterns; rendering tabs from a list where both an outlet and tab elements are present.
Related errors
- IonTabs must contain an IonRouterOutlet or an IonTab
- IonTabs must contain an IonRouterOutlet or an IonTab.
- IonTabs cannot contain an IonRouterOutlet and IonTab at the
- Cannot activate an already activated outlet
- no views in the stack to be removed
AI-assisted analysis of ionic-team/ionic-framework@625f9c38ad (2026-08-12).
Data as JSON: /api/errors/379a9fc4aa2a319a.
Report an issue: GitHub.