diff --git a/packages/angular/src/errorhandler.ts b/packages/angular/src/errorhandler.ts index 9d72c8cbc2bd..3dcecee1738b 100644 --- a/packages/angular/src/errorhandler.ts +++ b/packages/angular/src/errorhandler.ts @@ -2,6 +2,19 @@ import { HttpErrorResponse } from '@angular/common/http'; import { ErrorHandler as AngularErrorHandler, Injectable } from '@angular/core'; import * as Sentry from '@sentry/browser'; +// That's the `global.Zone` exposed when the `zone.js` package is used. +// eslint-disable-next-line @typescript-eslint/no-explicit-any +declare const Zone: any; + +// There're 2 types of Angular applications: +// 1) zone-full (by default) +// 2) zone-less +// The developer can avoid importing the `zone.js` package and tells Angular that +// he is responsible for running the change detection by himself. This is done by +// "nooping" the zone through `CompilerOptions` when bootstrapping the root module. +// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access +const isNgZoneEnabled = typeof Zone !== 'undefined' && !!Zone.current; + /** * Options used to configure the behavior of the Angular ErrorHandler. */ @@ -38,7 +51,16 @@ class SentryErrorHandler implements AngularErrorHandler { const extractedError = this._extractError(error) || 'Handled unknown error'; // Capture handled exception and send it to Sentry. - const eventId = Sentry.captureException(extractedError); + const eventId = isNgZoneEnabled + ? // The `Zone.root.run` basically will capture the exception in the most parent zone. + // The Angular's zone is forked from the `Zone.root`. In this case, `zone.js` won't + // trigger change detection, and `ApplicationRef.tick()` will not be run. + // Caretaker note: we're using `Zone.root` except `NgZone.runOutsideAngular` since this + // will require injecting the `NgZone` facade. That will create a breaking change for + // projects already using the `SentryErrorHandler`. + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + Zone.root.run(() => Sentry.captureException(extractedError)) + : Sentry.captureException(extractedError); // When in development mode, log the error to console for immediate feedback. if (this._options.logErrors) {