Skip to content

fix(angular): guard transition against destroyed router outlet - #31297

Merged
ShaneK merged 1 commit into
ionic-team:mainfrom
adahlberg-sprocket-sports:fix/stack-controller-destroyed-outlet
Jul 28, 2026
Merged

fix(angular): guard transition against destroyed router outlet#31297
ShaneK merged 1 commit into
ionic-team:mainfrom
adahlberg-sprocket-sports:fix/stack-controller-destroyed-outlet

Conversation

@adahlberg-sprocket-sports

Copy link
Copy Markdown
Contributor

Issue number: resolves #31296


What is the current behavior?

StackController.destroy() sets this.containerEl = undefined!, but a transition that is still queued behind wait() can resolve after the ion-router-outlet was destroyed (interrupted / re-entrant / cancelled navigation during fast back-navigation). transition() then dereferences the undefined element at if ((containerEl as any).commit) and throws:

TypeError: undefined is not an object (evaluating 'containerEl.commit')
    at transition

Observed at production scale in an Ionic Angular + Capacitor app (several hundred RUM crash events per week from a single build, concentrated on rapid back-navigation between nested outlets).

What is the new behavior?

  • transition() null-checks containerEl (optional chaining) before probing for commit.
  • A transition resolving after its outlet was destroyed now takes the method's existing fallback path and resolves false, instead of throwing an unhandled TypeError.
  • No behavior change for live outlets.

Regarding tests: there is no existing unit harness for StackController (only the e2e test apps), and the defect is a timing race between a queued transition and outlet destruction, which is impractical to reproduce deterministically in e2e. The change is a defensive null-check on a field that destroy() explicitly sets to undefined (with a lint-suppressed non-null assertion). We have run this exact guard in production via patch-package: the crash class disappears with no observed regressions.

Does this introduce a breaking change?

  • Yes
  • No

Other information

The unguarded dereference is present in v8.8.13 through latest stable 8.8.15 and 8.8.16-nightly.20260724.

StackController.destroy() sets containerEl to undefined, but a queued
transition can resolve after its ion-router-outlet was destroyed
(interrupted, re-entrant, or cancelled navigation). The commit guard
dereferenced containerEl unconditionally, throwing
"TypeError: undefined is not an object (evaluating 'containerEl.commit')"
during normal back-navigation. Null-check containerEl so a transition
against a destroyed outlet resolves to false instead of crashing.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@vercel

vercel Bot commented Jul 25, 2026

Copy link
Copy Markdown

@adahlberg-sprocket-sports is attempting to deploy a commit to the Ionic Team on Vercel.

A member of the Team first needs to authorize it.

@github-actions github-actions Bot added the package: angular @ionic/angular package label Jul 25, 2026
@ShaneK
ShaneK merged commit fdef61c into ionic-team:main Jul 28, 2026
49 of 50 checks passed
@ShaneK

ShaneK commented Jul 28, 2026

Copy link
Copy Markdown
Member

Thanks for the PR! We've merged it and it'll be deployed in the next update!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

package: angular @ionic/angular package

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug: StackController transition crashes when router outlet is destroyed mid-transition

2 participants