ionic-team/ionic-framework · error · Error

incompatible reuse strategy

Error message

incompatible reuse strategy

What it means

Thrown by IonRouterOutlet.detach(). Ionic's outlet deliberately does not implement Angular's RouteReuseStrategy detach/attach lifecycle because it maintains its own navigation stack for page transitions. Calling detach is treated as an incompatible reuse strategy and fails immediately. The message is the contract: do not use a reuse strategy that detaches this outlet.

Source

Thrown at packages/angular/common/src/directives/navigation/router-outlet.ts:190

  get activatedRoute(): ActivatedRoute {
    if (!this.activated) {
      throw new Error('Outlet is not activated');
    }
    return this._activatedRoute as ActivatedRoute;
  }

  get activatedRouteData(): Data {
    if (this._activatedRoute) {
      return this._activatedRoute.snapshot.data;
    }
    return {};
  }

  /**
   * Called when the `RouteReuseStrategy` instructs to detach the subtree
   */
  detach(): ComponentRef<any> {
    throw new Error('incompatible reuse strategy');
  }

  /**
   * Called when the `RouteReuseStrategy` instructs to re-attach a previously detached subtree
   */
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
  attach(_ref: ComponentRef<any>, _activatedRoute: ActivatedRoute): void {
    throw new Error('incompatible reuse strategy');
  }

  deactivate(): void {
    if (this.activated) {
      if (this.activatedView) {
        // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
        const context = this.getContext()!;
        this.activatedView.savedData = new Map(context.children['contexts']);

        /**

View on GitHub (pinned to 625f9c38ad)

Solutions

  1. Do not use a RouteReuseStrategy that detaches; Ionic already caches pages in its stack.
  2. If you must use one, scope shouldDetach/shouldAttach to return false for routes rendered by ion-router-outlet.
  3. Remove or replace the global custom reuse strategy with Ionic's NavController-based stacking.
  4. If you need scroll/state preservation, use Ionic's ion-page lifecycle events instead of route reuse.

Example fix

// before
@Injectable()
export class MyReuseStrategy extends RouteReuseStrategy {
  shouldDetach(): boolean { return true; } // forces detach() on ion-router-outlet
}

// after
shouldDetach(route: ActivatedRouteSnapshot): boolean {
  // never detach routes inside ion-router-outlet
  return false;
}
Defensive patterns

Strategy: fallback

Validate before calling

@Injectable()
class SafeReuseStrategy extends RouteReuseStrategy {
  shouldDetach(): boolean { return false; }      // never detach ion-router-outlet
  shouldAttach(): boolean { return false; }
  retrieve(): DetachedRouteHandle | null { return null; }
  shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean {
    return future.routeConfig === curr.routeConfig;
  }
}

Prevention

When it happens

Trigger: An Angular RouteReuseStrategy (custom or from a library) calls outlet.detach() - typically because shouldDetachRoute returned true. Any strategy that tries to lift the outlet's subtree out for reuse triggers it.

Common situations: Adding a custom RouteReuseStrategy for tab caching or 'back navigation' preservation that detaches routes; using a third-party reuse-strategy library globally; following a generic Angular tutorial that enables detachment without scoping it away from ion-router-outlet.

Related errors


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