HELP :: Navigation triggered outside Angular zone

Navigation triggered outside Angular zone, did you forget to call ‘ngZone.run()’?

All of a sudden my app started to give this warning and at certain pages, it redirects to default page (login)…

Any help???

Ionic:

ionic (Ionic CLI) : 4.10.3 (C:\Users\pnaan_000\AppData\Roaming\npm\node_modules\ionic)
Ionic Framework : @ionic/angular 4.0.2
@angular-devkit/build-angular : 0.12.4
@angular-devkit/schematics : 7.2.4
@angular/cli : 7.3.3
@ionic/angular-toolkit : 1.3.0

Cordova:

cordova (Cordova CLI) : 8.1.2 (cordova-lib@8.1.1)
Cordova Platforms : android 7.1.4
Cordova Plugins : cordova-plugin-ionic-keyboard 2.1.3, cordova-plugin-ionic-webview 3.1.2, (and 7 other plugins)

System:

Android SDK Tools : 26.1.1 (C:\Android\studio)
NodeJS : v10.13.0 (C:\Program Files\nodejs\node.exe)
npm : 6.7.0
OS : Windows 10

It happened in pages where i was using [href] as opposite to [routerlink].
As soon as I changed to routerlink, all worked out!

I also have the problem suddenly when I click a link of my ion-menu, then my target page crashes suddenly.
It all worked before.

this is the error message:
it can not read the valid-property of my form-field.
Also see the warning before.

Ionic:

Ionic CLI : 5.4.6 (/Users/oliverwaterkamp/node_modules/ionic)
Ionic Framework : @ionic/angular 4.11.10
@angular-devkit/build-angular : 0.803.25
@angular-devkit/schematics : 8.1.3
@angular/cli : 8.3.25
@ionic/angular-toolkit : 2.1.2

Capacitor:

Capacitor CLI : 1.4.0
@capacitor/core : 1.4.0

Utility:

cordova-res : not installed
native-run : not installed

System:

NodeJS : v12.13.0 (/usr/local/bin/node)
npm : 6.13.6
OS : macOS Catalina

I think it’s going to be tough for anybody to say much constructive without having access to an MCVE, but you did mention one thing:

This is where version control really comes in handy. If you make changes only on branches, it’s easy to revert to “before” and compare in (relatively) leisurely detail what triggered the problem.

Thx for your quick feedback…
and yeah your’re abolutely right…
I will further investigate it and come back as soon I have more detail or the solution…

I also saw following threat:

But I could not figure out whether it was solved or not.

I think I found the problem of the warning (still not the cause of the error)…
Within my global error handler I tried to write redirect to a special error-page.

router.navigate(['/error']);

I removed this now and the warning ‘Navigation triggered outside of Angular zone’ seems to be disappeared.

So this means for me this is not the problem, which causes my error…

As soon I know more I let you know…

One of the trickiest parts about writing apps for MacOS back in the pre-Darwin days was trap patching. It was sort of like the prototype shenanigans people do in JavaScript to modify the behavior of built-in objects, but even more powerful and dangerous. Apple basically used illegal instructions (from the CPU’s POV) to implement the OS. The illegal instruction would suspend whatever the CPU was ordinarily doing and jump to a fixed place, where the OS would do its thing, and then return control to normal.

When you patched these OS routines, you had to be super-careful about what other parts of the OS you called, because much of it wasn’t reentrant and you could crash the entire computer, frequently in intermittent and hard-to-reproduce fashion. The safest thing to do in a trap patch was simply to set a flag and wait for a more predictable time to respond to it.

Maybe a page from that book would help you here. Instead of doing anything heavy in a “global error handler” (which sounds like something that can get called from all sorts of sketchy situations), just throw up a flare in there and react to it in a safer environment:

class ErrorService {
  private errors$ = new Subject<string>();
  watchErrors(): Observable<string> { return this.errors$; }
  globalErrorHandler() {
    this.errors$.next("ruh roh");
  }
}
// could be anywhere, really, but I know there's an AppComponent
class AppComponent {
  constructor(router: Router, errorer: ErrorService) {
    errorer.watchErrors().subscribe(err => router.navigate(["/error"]);
  }
}

Promise.resolve can be used to similar effect: both RxJS and Promise are zone-aware, so by the time the Observable's emission is seen by the subscribe block (or a then block in the Promise case), you are going to be back in the Angular zone, even if the globalErrorHandler happened to be called from outside it.

One thing I would definitely not do (although you’ll likely see others who disagree) is to inject NgZone and call its run method. I feel zones are an internal implementation detail of Angular, and shouldn’t be in app code.

1 Like

Thank you for the amazing support and for giving me all those tips.
It’s very valuable for me.

I wasn’t aware of that, that this routing within the global error handler is not right…
But I was aware of that the global error handler needs to be treated carefully :slight_smile:

Thank you also for you code snippet. I will try to used it like this.

The other error did not appear again until now.

So I think we can close this threat.

Really sorry for my little panic-mode, but I learn fast and I will take up all of your suggestions.

Thx,
Oliver