ionic-team/ionic-framework · error · Error
inserted view was already destroyed
Error message
inserted view was already destroyed
What it means
Thrown in IonNav.prepareTI() when an inserted view's `state` is `VIEW_STATE_DESTROYED`. Once a view has been destroyed (removed and torn down by the nav), it cannot be re-inserted because its DOM and lifecycle resources are gone. The nav refuses to revive a destroyed controller.
Source
Thrown at core/src/components/nav/nav.tsx:742
if (!insertViews) {
return;
}
assert(insertViews.length > 0, 'length can not be zero');
const viewControllers = convertToViews(insertViews);
if (viewControllers.length === 0) {
throw new Error('invalid views to insert');
}
// Check all the inserted view are correct
for (const view of viewControllers) {
view.delegate = ti.opts.delegate;
const nav = view.nav;
if (nav && nav !== this) {
throw new Error('inserted view was already inserted');
}
if (view.state === VIEW_STATE_DESTROYED) {
throw new Error('inserted view was already destroyed');
}
}
ti.insertViews = viewControllers;
}
/**
* Returns the view that will be entered considering the transition instructions.
*
* @param ti The instructions.
* @param leavingView The view being left or undefined if none.
*
* @returns The view that will be entered, undefined if none.
*/
private getEnteringView(
ti: TransitionInstruction,
leavingView: ViewController | undefined
): ViewController | undefined {
// The last inserted view will be entered when view are inserted.View on GitHub (pinned to 625f9c38ad)
Solutions
- Never re-insert a destroyed ViewController; always insert the component class/element and let the nav build a new view.
- Discard cached controller references once the view has been popped.
- If you need stateful reuse, store the component props and re-create the view via setRoot/push with those props.
- Audit for any code path that retains `getActive()`/`getByIndex()` results across pop operations.
Example fix
// before
const view = nav.getActive();
await nav.pop();
await nav.push(view); // view is destroyed -> throws
// after
const { component, componentProps } = view;
await nav.pop();
await nav.push(component, componentProps); Defensive patterns
Strategy: validation
Validate before calling
// Do not re-insert destroyed views; check state if you must reuse a reference
import { VIEW_STATE_DESTROYED } from '@ionic/core'; // conceptual
if (viewController.state === VIEW_STATE_DESTROYED) {
throw new Error('Cannot re-insert a destroyed view. Push its component instead.');
}
await nav.push(viewController.component, viewController.componentProps); Type guard
function isLiveView(view: ViewController): boolean {
return view && view.state !== VIEW_STATE_DESTROYED;
} Prevention
- Discard controller references once a view is popped.
- Re-create views from their component + props, not from cached controllers.
- Avoid view-pooling strategies that retain destroyed controllers.
When it happens
Trigger: Passing a ViewController that was previously popped (and thus destroyed) back into `insert`/`push`/`setPages`/`setRoot`; caching a view reference and reusing it after the nav destroyed it.
Common situations: Holding a reference from `nav.getActive()` or `nav.getByIndex()`, popping the view, then trying to push the same controller again; pooling/caching views for performance and reusing them after destruction.
Related errors
- no views in the stack to be removed
- navigation stack needs at least one root page
- removeView was not found
- invalid views to insert
- inserted view was already inserted
AI-assisted analysis of ionic-team/ionic-framework@625f9c38ad (2026-08-12).
Data as JSON: /api/errors/67139541c1737d96.
Report an issue: GitHub.