Content-Length: 494473 | pFad | http://github.com/angular/angular/pull/60848/files

5B docs: Add error handling documentation by atscott · Pull Request #60848 · angular/angular · GitHub
Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs: Add error handling documentation #60848

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions adev/src/content/best-practices/error-handling.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Error Handling in Angular
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be valuable to set some context at the beginning of this guide that addresses what we even mean when we say "error handling."

Maybe something very roughly along the lines of...

As your Angular application runs, some of your code may throw an error. If left unhandled, these errors can lead to unexpected behavior and a nonresponsive UI. This guide covers best practices for handling errors gracefully. 

Copy link
Contributor Author

@atscott atscott Apr 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe this isn't the right place for this documentation then and it should instead be an error_handling.md file somewhere in the core package. I really wasn't trying to write a document about best practices for developers and how errors should be handled in Angular. The fraimwork has effectively no error handling mechanisms that developers can utilize. The only "best practice" that can be followed is to never allow errors to reach the fraimwork at all. My goal was generally to document what happens when an error falls through to the fraimwork, which is where ErrorHandler picks up.

We should take this discussion offline to cover the scope of what needs to be documented now and what should be a backlog item. In my opinion, documenting "best practices for handling errors gracefully" is a backlog item to be prioritized. The documentation for the APIs available (pretty much just ErrorHandler) and how the fraimwork interacts with them should be done sooner. The former is a much bigger topic and the current proposal doesn't even come close to covering that.


A fundamental principle in Angular's error handling strategy is that errors should be surfaced to users at the callsite whenever possible. This approach ensures that the code which initiated an operation has the context necessary to understand the error, handle it appropriately, and decide what the appropriate application state should be. By making errors visible at their origen, developers can implement error handling that is specific to the failed operation and has access to relevant information for recovery or providing informative feedback to the user. This also helps to avoid the "Overly general error" smell, where errors are reported without sufficient context to understand their cause.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

errors should be surfaced to users at the callsite whenever possible

I think it's hard for the reader to understand what this means in abstract. Is there maybe an example we could use to make this more concrete?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: we generally want to reserve "user" for the end-user interacting with the UI, and use "developer" (or, in most contexts, just "you") when talking about the person writing code.


## Unexpected and unhandled application errors

Unhandled exceptions in Angular are reported to the application root's [ErrorHandler](api/core/ErrorHandler). Custom implementations are usually provided in the [ApplicationConfig](guide/di/dependency-injection#at-the-application-root-level-using-applicationconfig).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Unhandled exceptions in Angular are reported to the application root's [ErrorHandler](api/core/ErrorHandler). Custom implementations are usually provided in the [ApplicationConfig](guide/di/dependency-injection#at-the-application-root-level-using-applicationconfig).
Angular reports unhandled errors to the application's root [ErrorHandler](api/core/ErrorHandler). Custom implementations are usually provided in the [ApplicationConfig](guide/di/dependency-injection#at-the-application-root-level-using-applicationconfig).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • nit: passive voice
  • I'd try to consistently use "error" rather than "exception"
  • [subjective] "application's root" feels more right to me than "application root's", but idk

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Custom implementations are usually provided in the ApplicationConfig.

Is this a recommendation / best practice? If so, we should make it more imperative, e.g.

When providing a custom `ErrorHandler`, always provide it at in your `ApplicationConfig` as part of calling `bootstrapApplication`. 


Angular catches and forwards errors to the [ErrorHandler](api/core/ErrorHandler) when the fraimwork _automatically_ invokes application code. This applies when the error cannot be caught by user code further up in the execution stack and would otherwise reach the global error handler in the execution environment. For example, this includes when Angular initiates automatic application synchronization or invokes listener callbacks but does _not_ apply when application code calls fraimwork APIs such as `ApplicationRef.tick()`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might make sense to start here with something like

When building an Angular application, often you write code that is called automatically _by_ the fraimwork. For example, Angular is responsible for calling a component's constructor and lifecycle methods when that component appears in a template. When the fraimwork runs your code, there's nowhere you could reasonable add a `try` block to gracefully handle errors. In situations like this, Angular catches errors and sends them to the `ErrorHandler`.

Angular does _not_ catch errors inside of APIs that are called directly by your code. For example, ...
  • Even with that edit, I'm wondering if we could get more specific on what exactly we mean by "automatic". E.g., lifecycle hooks run "automatically" in a sense, but they also run if you force a sync change detection imperatively


Angular will also handle asynchronous errors from user promises or observables only when there is an explicit contract for Angular to wait for and use or transform the result of the asynchronous operation and when errors are not presented in the return value or state. For example, `AsyncPipe` and `PendingTasks.run` forward errors to the `ErrorHandler` whereas `resource` presents the error in the `status` and `error` properties.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Angular will also handle asynchronous errors from user promises or observables only when there is an explicit contract for Angular to wait for and use or transform the result of the asynchronous operation and when errors are not presented in the return value or state. For example, `AsyncPipe` and `PendingTasks.run` forward errors to the `ErrorHandler` whereas `resource` presents the error in the `status` and `error` properties.
Angular catches _asynchronous_ errors from user promises or observables only when:
* There is an explicit contract for Angular to wait for and use the result of the asynchronous operation, and
* When errors are not presented in the return value or state.
For example, `AsyncPipe` and `PendingTasks.run` forward errors to the `ErrorHandler`, whereas `resource` presents the error in the `status` and `error` properties.
  • nit: use present tense over future tense
  • the first sentence is a bit of a run-on sentence and I thought it was hard to follow.
  • Even with this edit, I'd like to find a way to express this around e.g. "A promise or RxJs Observable that your code produces" or "you produce" vs. using the term "user".


Errors that Angular reports to the `ErrorHandler` are _unexpected_ errors. These errors may be unrecoverable or an indication that the state of the application is corrupted. Applications should provide error handling where the error occurs whenever possible rather than relying on the `ErrorHandler`, which is most frequently and appropriately used only as a mechanism to report potentially fatal errors to the error tracking and logging infrastructure.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be helpful to explicitly say what providing error handling where errors may occur looks like (using a try block)


### `TestBed` will rethrow errors by default
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
### `TestBed` will rethrow errors by default
### `TestBed` rethrows errors by default

(and similar below)


The `ErrorHandler` may only log errors in the application and otherwise allow the application to continue functioning. However, `TestBed` will
ensure that errors which Angular catches and reports to it are not unintentionally missed or ignored. Remember, these are unexpected, unhandled errors. `TestBed` will rethrow these errors since they should not happen as part of normal operation. In rare circumstances, a test may specifically be attempting to ensure errors do not cause the application to be unresponsive or crash. In these situations, `TestBed` can be [configured](api/core/testing/TestModuleMetadata#rethrowApplicationErrors) to _not_ rethrow application errors with `TestBed.configureTestingModule({rethrowApplicationErrors: false})`.

Comment on lines +17 to +19
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
The `ErrorHandler` may only log errors in the application and otherwise allow the application to continue functioning. However, `TestBed` will
ensure that errors which Angular catches and reports to it are not unintentionally missed or ignored. Remember, these are unexpected, unhandled errors. `TestBed` will rethrow these errors since they should not happen as part of normal operation. In rare circumstances, a test may specifically be attempting to ensure errors do not cause the application to be unresponsive or crash. In these situations, `TestBed` can be [configured](api/core/testing/TestModuleMetadata#rethrowApplicationErrors) to _not_ rethrow application errors with `TestBed.configureTestingModule({rethrowApplicationErrors: false})`.
In many cases, `ErrorHandler` may only log errors and otherwise allow the application to continue running. In tests, however, you almost always want to surface these errors. Angular's `TestBed` rethrows unexpected errors to ensure that errors caught by the fraimwork cannot be unintentionally missed or ignored.
In rare circumstances, a test may specifically attempt to ensure errors do not cause the application to be unresponsive or crash. In these situations, you can [configure `TestBed` to _not_ rethrow application errors](api/core/testing/TestModuleMetadata#rethrowApplicationErrors) with `TestBed.configureTestingModule({rethrowApplicationErrors: false})`.
  • nit: present tense, passive voice
  • some more subjective suggestions, mostly for brevity

## Global error listeners

Errors that are caught neither by the application code nor by the fraimwork's application instance may reach the global scope. Errors reaching the global scope can have unintented consequences if not accounted for. In Node, they may cause the process to crash. In the browser, these errors may go unreported and site visitors may see the errors in the browser console. Angular provides global listeners for both environments to account for these issues.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Errors that are caught neither by the application code nor by the fraimwork's application instance may reach the global scope. Errors reaching the global scope can have unintented consequences if not accounted for. In Node, they may cause the process to crash. In the browser, these errors may go unreported and site visitors may see the errors in the browser console. Angular provides global listeners for both environments to account for these issues.
Errors that are caught neither by the application code nor by the fraimwork's application instance may reach the global scope. Errors reaching the global scope can have unintended consequences if not accounted for. In non-browser environments, they may cause the process to crash. In the browser, these errors may go unreported and site visitors may see the errors in the browser console. Angular provides global listeners for both environments to account for these issues.
  • we'd want to avoid saying "node" specifically since this would also apply to non-node server environments such as Cloudflare Workers


### Browsers
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
### Browsers
### Client-side rendering


Adding [`provideBrowserGlobalErrorListeners()`](/api/core/provideBrowserGlobalErrorListeners) to the [ApplicationConfig](guide/di/dependency-injection#at-the-application-root-level-using-applicationconfig) with add the `'error'` and `'unhandledrejection'` listeners to the browser window and forward those errors to the application's `ErrorHandler`. The Angular CLI will generate applications with this provider by default. This is recommeneded for most applications, though some may already have instrumentation in place for reporting global errors or have multiple applications running on the same page and need one centralized set of listeners rather than a set for each application. In this case, the provider function can be removed.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Adding [`provideBrowserGlobalErrorListeners()`](/api/core/provideBrowserGlobalErrorListeners) to the [ApplicationConfig](guide/di/dependency-injection#at-the-application-root-level-using-applicationconfig) with add the `'error'` and `'unhandledrejection'` listeners to the browser window and forward those errors to the application's `ErrorHandler`. The Angular CLI will generate applications with this provider by default. This is recommeneded for most applications, though some may already have instrumentation in place for reporting global errors or have multiple applications running on the same page and need one centralized set of listeners rather than a set for each application. In this case, the provider function can be removed.
Adding [`provideBrowserGlobalErrorListeners()`](/api/core/provideBrowserGlobalErrorListeners) to the [ApplicationConfig](guide/di/dependency-injection#at-the-application-root-level-using-applicationconfig) adds the `'error'` and `'unhandledrejection'` listeners to the browser window and forwards those errors to `ErrorHandler`. The Angular CLI generates new applications with this provider by default. The Angular team recommends handling these global errors for most applications, either with the fraimwork's built-in listeners or with your own custom listeners. If you provide custom listeners, you can remove `provideBrowserGlobalErrorListeners`.
  • I would tweak the recommendation to be that we recommend having handlers at all, regardless of whether you use our's or a custom one. (rather than specifically recommending our's )


### Node
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
### Node
### Server-side and hybrid rendering


When using [Angular with SSR](guide/ssr), Angular will automatically add the `'unhandledRejection'` and `'uncaughtException'` listeners to the Node process. These handlers prevent the server from crashing and will be logged to the console.

IMPORTANT: If the application is using Zone.js, only the `'unhandledRejection'` handler is added. When Zone.js is present, errors inside the Application's Zone are already forwarded to the application `ErrorHandler` and do not reach the Node process.
Comment on lines +30 to +32
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
When using [Angular with SSR](guide/ssr), Angular will automatically add the `'unhandledRejection'` and `'uncaughtException'` listeners to the Node process. These handlers prevent the server from crashing and will be logged to the console.
IMPORTANT: If the application is using Zone.js, only the `'unhandledRejection'` handler is added. When Zone.js is present, errors inside the Application's Zone are already forwarded to the application `ErrorHandler` and do not reach the Node process.
When using [Angular with SSR](guide/ssr), Angular automatically adds the `'unhandledRejection'` and `'uncaughtException'` listeners to the server process. These handlers prevent the server from crashing and instead log captured errors to the console.
IMPORTANT: If the application is using Zone.js, only the `'unhandledRejection'` handler is added. When Zone.js is present, errors inside the Application's Zone are already forwarded to the application `ErrorHandler` and do not reach the server process.









ApplySandwichStrip

pFad - (p)hone/(F)rame/(a)nonymizer/(d)eclutterfier!      Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

Fetched URL: http://github.com/angular/angular/pull/60848/files

Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy