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

  1. Pass an index instead of a ViewController to `popTo(index)` if you are unsure the view reference is still live.
  2. 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()`.
  3. Do not reuse a ViewController instance after it has been removed; fetch a fresh reference from the nav.
  4. 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

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


AI-assisted analysis of ionic-team/ionic-framework@625f9c38ad (2026-08-12). Data as JSON: /api/errors/f806b2c3d820c5be. Report an issue: GitHub.