> ## Content Index
> Fetch the complete content index at: https://www.angularspace.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# How to Handle Global Errors in Modern Zoneless Angular
- URL: https://www.angularspace.com/how-to-handle-global-errors-in-modern-zoneless-angular/
- Published: 2026-08-04T11:51:30.000Z
- Updated: 2026-08-04T11:51:47.000Z
- Author: Jaroslaw Zolnowski

In the world of web development, unhandled errors are silent threats. They can degrade user experience, cause unpredictable application behavior, and leave developers in the dark. For years, Angular's error handling has benefited from a bit of "magic" provided by `Zone.js`. However, as the framework evolves towards a more explicit and performant zoneless future, that magic disappears, requiring a new approach. This is the primary reason [provideBrowserGlobalErrorListeners](https://angular.dev/api/core/provideBrowserGlobalErrorListeners?ref=angularspace.com) was introduced. It’s not just a new feature of the Angular v20, but a fundamental tool for robust error handling in modern, zoneless Angular. But lets start from the beginning.

![](https://storage.ghost.io/c/3f/63/3f6333b8-1f83-4017-8426-91bfbc264d81/content/images/2026/08/feature-image-1.png)

### Error Handling with Zone.js: The Old Magic

In a traditional, "Zone-full" Angular application, `Zone.js` acts like an invisible net cast over our application's execution context. It works by "monkey-patching" nearly all standard asynchronous browser APIs, such as `setTimeout`, `addEventListener`, and, critically, **`Promise`**.

Because `Zone.js` wraps these APIs, it gains awareness of almost every async task that begins and ends. This mechanism is primarily used to trigger Angular's change detection automatically. However, it provides a powerful side effect for error handling:

- **Automatic Interception:** When a `Promise` is rejected without a `.catch()` handler, `Zone.js`'s patched version of `Promise` is aware of this failure. It automatically intercepts the unhandled rejection and forwards it into Angular's execution context.
- **Centralized Errors:** The result is that these "outside" errors are seamlessly channeled to Angular's central [ErrorHandler](https://github.com/angular/angular/blob/v22.1.0/packages/core/src/error%5Fhandler.ts?ref=angularspace.com#L54), where they can be processed just like an error from a component or service. The `ErrorHandler` is a simple, injectable class that serves as a centralized hook for all exceptions caught within the Angular framework. Its [default implementation](https://github.com/angular/angular/blob/v22.1.0/packages/core/src/error%5Fhandler.ts?ref=angularspace.com#L60-L62) is straightforward. You can read more about it in the [Armens's article about Angular Error Handling](https://www.angularspace.com/angular-error-handling/)

This was convenient, but it relied on the implicit, pervasive nature of `Zone.js`.

### The Zoneless Challenge: When the Magic Disappears

A zoneless application, by definition, does **not** include `Zone.js`. This brings significant performance gains and makes application behavior more explicit, but it removes the invisible error-catching net.

So what happens when an error occurs outside of Angular's direct control in a zoneless application? Consider these common scenarios:

- **Unhandled Promise Rejections:** A `Promise` is rejected somewhere in our code, but we forgot to chain a `.catch()` handler.
- **Third-Party Scripts:** An error occurs inside a non-Angular, third-party library that manipulates the DOM or performs its own asynchronous tasks.
- **Asynchronous Operations:** A callback passed to a native browser API like `setTimeout` or an event listener added with `addEventListener` throws an error.

Without a specific mechanism in place, these errors would not be intercepted by Angular's `ErrorHandler`. They would be logged to the console but would exist outside our centralized error-handling logic, making them invisible to our logging and reporting services.

### The Solution: Building a Bridge with`provideBrowserGlobalErrorListeners`

This is precisely the problem `provideBrowserGlobalErrorListeners` solves. It serves as the explicit replacement for the implicit magic that Zone.js once provided for error handling.

Instead of patching anything, this provider sets up simple, native event listeners on the global window object for:

1. [error](https://github.com/angular/angular/blob/v22.1.0/packages/core/src/error%5Fhandler.ts?ref=angularspace.com#L125): Fired for general runtime script errors.
2. [unhandledrejection](https://github.com/angular/angular/blob/v22.1.0/packages/core/src/error%5Fhandler.ts?ref=angularspace.com#L121): Fired whenever a `Promise` is rejected without a handler to catch the rejection.

When one of these global events is triggered, the listener created by `provideBrowserGlobalErrorListeners` intercepts the raw error and \*\*forwards it to Angular's centralized `ErrorHandler` class.

This re-establishes the connection that was lost when Zone.js and creates a unified pipeline, ensuring that errors from third-party scripts, native browser APIs, or unhandled promises are treated the same as errors from within our components or services. This allows us to process every error in one central location, whether for logging, analytics, or displaying user-friendly notifications.

This function is a default part of the Angular's setup. When we create a new project using the Angular CLI, the `provideBrowserGlobalErrorListeners()` provider is automatically added to the `app.config.ts` file, ensuring that robust error handling is built-in from the very beginning.

`export const appConfig: ApplicationConfig = {  
 providers: [  
 provideBrowserGlobalErrorListeners(),  
 // ...  
 ]  
};`

### Implications for Testing

This improved error capturing has an important consequence for testing. Errors thrown in event listeners are now reported to the internal Angular error handler. This is a positive change for application quality, as it means we may see errors in our tests that were not reported before, uncovering previously hidden bugs.

The recommended approach is to fix the underlying issues causing these errors in our tests. However, if that's not immediately feasible, we have an escape hatch. We can configure the `TestBed` to prevent these errors from failing our test suite by setting `**rethrowApplicationErrors: false**` in the `configureTestingModule` setup as a last resort:

`TestBed.configureTestingModule({  
 // ... other testing module configuration  
 rethrowApplicationErrors: false, // Use only when necessary  
});`

### Customization and Best Practices

The Angular team **recommends handling these global errors for most applications**, and `provideBrowserGlobalErrorListeners` is the easiest way to do so. It offers a "plug-and-play" solution that integrates seamlessly with the framework.

However, Angular remains flexible. If our application has specific needs that require a different approach, we are free to implement our own custom listeners for the `window.error` and `window.unhandledrejection` events. If we choose to provide our own custom listeners, we can, and should **remove `provideBrowserGlobalErrorListeners`** from our `app.config.ts` providers to avoid setting up redundant handlers.

### Conclusion

`provideBrowserGlobalErrorListeners` is a valuable and effective utility for Angular developers. It offers a consistent way to catch errors that occur outside the Angular context, seamlessly integrating them into Angular’s error handling flow. As Angular continues to evolve, the importance of explicitly managing and handling errors becomes even more important. By leveraging `provideBrowserGlobalErrorListeners` and custom `ErrorHandler` implementations, we can create Angular applications that are more robust, stable, and user-focused.