ionic-team/ionic-framework · error · Error
removeView was not found
Error message
removeView was not found
What it means
Thrown in IonNav.prepareTI() when a TransitionInstruction carries a `removeView` (a ViewController passed to `popTo(viewController)`) but that ViewController is not present in `this.views` (`indexOf` returns -1). The nav cannot compute a removal range relative to a view it does not own.
Source
Thrown at core/src/components/nav/nav.tsx:700
this.failed(rejectReason, ti);
}
this.isTransitioning = false;
this.nextTrns();
}
private prepareTI(ti: TransitionInstruction) {
const viewsLength = this.views.length;
ti.opts ??= {};
ti.opts.delegate ??= this.delegate;
if (ti.removeView !== undefined) {
assert(ti.removeStart !== undefined, 'removeView needs removeStart');
assert(ti.removeCount !== undefined, 'removeView needs removeCount');
const index = this.views.indexOf(ti.removeView);
if (index < 0) {
throw new Error('removeView was not found');
}
ti.removeStart! += index;
}
if (ti.removeStart !== undefined) {
if (ti.removeStart < 0) {
ti.removeStart = viewsLength - 1;
}
if (ti.removeCount! < 0) {
ti.removeCount = viewsLength - ti.removeStart;
}
ti.leavingRequiresTransition = ti.removeCount! > 0 && ti.removeStart + ti.removeCount! === viewsLength;
}
if (ti.insertViews) {
// allow -1 to be passed in to auto push it on the end
// and clean up the index if it's larger then the size of the stack
if (ti.insertStart! < 0 || ti.insertStart! > viewsLength) {
ti.insertStart = viewsLength;View on GitHub (pinned to 625f9c38ad)
Solutions
- Pass an index instead of a ViewController to `popTo(index)` if you are unsure the view reference is still live.
- Before calling `popTo(viewController)`, verify the view is still in this nav: `(await nav.getByIndex(await nav.getLength()-1))` lookup or compare against `nav.getViews()`.
- Do not reuse a ViewController instance after it has been removed; fetch a fresh reference from the nav.
- Ensure the same IonNav instance that inserted the view is the one you popTo.
Example fix
// before
await nav.popTo(cachedViewController);
// after
const views = nav.getViews();
const idx = views.indexOf(cachedViewController);
if (idx >= 0) {
await nav.popTo(idx);
} Defensive patterns
Strategy: validation
Validate before calling
// Validate the controller still belongs to this nav before popTo(viewController)
const views = nav.getViews();
if (!views.includes(viewController)) {
throw new Error('ViewController is not in this nav; cannot popTo it.');
}
await nav.popTo(views.indexOf(viewController)); Type guard
function viewBelongsToNav(nav: HTMLIonNavElement, view: ViewController): boolean {
return nav.getViews().includes(view);
} Try / catch
try {
await nav.popTo(viewController);
} catch (e) {
if ((e as Error).message === 'removeView was not found') {
// fall back to popping to an index instead of a stale controller
await nav.popTo(await nav.getLength() - 1);
} else {
throw e;
}
} Prevention
- Prefer index-based popTo over ViewController-based when references may be stale.
- Do not retain ViewController references after they are popped.
- Verify ownership with nav.getViews().includes(view) before popTo.
When it happens
Trigger: Calling `nav.popTo(viewController)` where `viewController` was never inserted into this nav, was already removed, or belongs to a different nav instance. `popTo` only sets `removeView` when passed an object with a `.component` property (a ViewController).
Common situations: Caching a ViewController reference across navigations and reusing it after it was popped/destroyed; calling popTo with a view from a sibling/parent IonNav; mixing router-managed and manually-pushed views so the reference is stale.
Related errors
- inserted view was already inserted
- no views in the stack to be removed
- invalid views to insert
- inserted view was already destroyed
- navigation stack needs at least one root page
AI-assisted analysis of ionic-team/ionic-framework@625f9c38ad (2026-08-12).
Data as JSON: /api/errors/f806b2c3d820c5be.
Report an issue: GitHub.