ionic-team/ionic-framework · error · Error

no views in the stack to be removed

Error message

no views in the stack to be removed

What it means

Thrown inside IonNav.runTransition() when, after prepareTI(), there is no leaving view AND no entering view to transition. This means the nav's view stack is empty and the queued transition neither inserts nor resolves to an existing view. The thrown error rejects the transition promise via the surrounding catch → failed() handler.

Source

Thrown at core/src/components/nav/nav.tsx:641

      return false;
    }
    this.runTransition(ti);
    return true;
  }

  /** Executes all the transition instruction from the queue. */
  private async runTransition(ti: TransitionInstruction) {
    try {
      // set that this nav is actively transitioning
      this.ionNavWillChange.emit();
      this.isTransitioning = true;
      this.prepareTI(ti);

      const leavingView = this.getActiveSync();
      const enteringView = this.getEnteringView(ti, leavingView);

      if (!leavingView && !enteringView) {
        throw new Error('no views in the stack to be removed');
      }

      if (enteringView && enteringView.state === VIEW_STATE_NEW) {
        await enteringView.init(this.el);
      }
      this.postViewInit(enteringView, leavingView, ti);

      // Needs transition?
      const requiresTransition =
        (ti.enteringRequiresTransition || ti.leavingRequiresTransition) && enteringView !== leavingView;
      if (requiresTransition && ti.opts && leavingView) {
        const isBackDirection = ti.opts.direction === 'back';

        /**
         * If heading back, use the entering page's animation
         * unless otherwise specified by the developer.
         */
        if (isBackDirection) {

View on GitHub (pinned to 625f9c38ad)

Solutions

  1. Ensure `nav.setRoot(...)` (or at least one `push`) has resolved before calling `pop()`/`popToRoot()`.
  2. Guard the call: check `await nav.getLength() > 0` (or `nav.canGoBack()`) before popping.
  3. Initialize the nav with a root page via the `root`/`rootParams` component property or setRoot on mount.
  4. If popping from a hardware/browser back handler, no-op when the stack is empty instead of calling pop.

Example fix

// before
const nav = await this.navRef.getNativeRef();
await nav.pop();
// after
if (await nav.getLength() > 0) {
  await nav.pop();
}
Defensive patterns

Strategy: validation

Validate before calling

// Before popping, ensure the nav actually has views
const length = await nav.getLength();
if (length === 0) {
  console.warn('Nav is empty; skipping pop.');
  return;
}
await nav.pop();

Try / catch

try {
  await nav.pop();
} catch (e) {
  if ((e as Error).message === 'no views in the stack to be removed') {
    // nav was empty — initialize a root page instead
    await nav.setRoot(HomePage);
  } else {
    throw e;
  }
}

Prevention

When it happens

Trigger: Calling `pop()`, `popToRoot()`, `popTo(...)`, or `removeIndex(...)` on a nav whose `views` array is empty (no setRoot was ever called), so getActiveSync() returns undefined and getEnteringView() also returns undefined.

Common situations: Invoking nav.pop() before any nav.setRoot()/push(); popping a nav whose root was destroyed; race where setRoot has not yet completed before pop is queued; programmatic back button handler firing on a freshly mounted empty nav.

Related errors


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