fix(platform-server): propagate errors from lifecycle hooks when utilizing platform-server#55787
fix(platform-server): propagate errors from lifecycle hooks when utilizing platform-server#55787alan-agius4 wants to merge 1 commit intoangular:mainfrom
Conversation
81d2845 to
cdee9c8
Compare
f4be47b to
88b383e
Compare
…izing platform-server In previous versions, if an error occurred within the lifecycle hooks, the promises for `renderModule` and `renderApplication` were not rejected. This could result in serving a "broken" page during Server-Side Rendering (SSR), or the build erroneously being marked as successful during Static Site Generation (SSG). Fixes angular#33642
88b383e to
8a21cf8
Compare
|
Hey @alan-agius4,
I hope you don't mind that I added this comment directly to this PR. Best regards! |
|
Hi @alan-agius4 Did you consider making the The Analogically, we need the hook of "last moment" allowing to access DI and modify the final error (or returning a brand new error object - use case: return a custom "wrapper Error object" with the If you don't want to expose in the public API the whole |
|
Hi @alan-agius4, Thank you so much for all the hard work you put into improving Angular SSR in various fields. And thank you for your efforts on this PR. I truly believe Async Error Handling is a significant improvement for Angular SSR/Prerendering. I noticed the PR was recently closed, and I understand that there might be higher priorities on the Angular team's roadmap or perhaps a different approach might be in the works. If it's a matter of having too many other duties, I'd be more than happy to help and contribute in any way I can. Please feel free to let me know how we could possibly collaborate to make Angular SSR Async Error Handling happen 😊 Thanks again! |
| /** | ||
| * Intecept unhandled promise rejections. | ||
| * This is crucial to prevent server crashes in scenarios where Zone.js is not utilized, and to avoid application | ||
| * build to succeed incorrectly during SSG when async errors occurring within life-cycle hooks, listeners and other. | ||
| * The framework currently lacks proper handling of async methods, leading to unhandled promise rejections. This issue needs to be rectified in future. | ||
| */ | ||
| private interceptUnhandledRejection(): void { | ||
| if (typeof process !== 'undefined') { | ||
| const listener: (reason: unknown, promise: Promise<unknown>) => void = (reason) => | ||
| this.onError(reason); | ||
| process.on('unhandledRejection', listener); | ||
| this.unlistenUnhandledRejection = () => | ||
| process.removeListener('unhandledRejection', listener); | ||
| } else if ('addEventListener' in globalThis) { | ||
| const listener = (event: PromiseRejectionEvent) => { | ||
| this.onError(event.reason); | ||
| event.preventDefault(); | ||
| }; | ||
|
|
||
| addEventListener('unhandledrejection', listener); | ||
| this.unlistenUnhandledRejection = () => removeEventListener('unhandledrejection', listener); | ||
| } | ||
| } |
There was a problem hiding this comment.
Hi @alan-agius4
The framework currently lacks proper handling of async methods, leading to unhandled promise rejections. This issue needs to be rectified in future.
This is a serious limitation, isn't it? If I understand correctly, without ZoneJS we're not able to "wrap" the execution context of the rendered app and associate errors happneing asynchronously within this context with the appropriate ErrorInterceptor.
In other words, if I render simultaneously 2 Angular apps for 2 incoming requests on the same ExpressJS process, then - if we add a global listener addEventListener('unhandledrejection', ...) 2 times - in each ErrorInterceptor of each app. Then in case of an async error in just one of those 2 apps, then both globally-registered listeners will fire, and both ErrorInterceptors onError() will be invoked, which would be a bug.
Perhaps we could address this problem by wrapping each rendering of each app via a native NodeJS Async Context. That said, I didn't explore this option yet - it's just an idea from top of my head.
|
This issue has been automatically locked due to inactivity. Read more about our automatic conversation locking policy. This action has been performed automatically by a bot. |
Implement the `attachNodeGlobalErrorHandlers` function to handle 'unhandledRejection' and 'uncaughtException' events in Node.js. This function logs errors to the console, preventing unhandled errors from crashing the server. It is particularly useful for zoneless apps, ensuring error handling without relying on zones. Closes angular/angular#58123
In previous versions, if an error occurred within the lifecycle hooks, the promises for
renderModuleandrenderApplicationwere not rejected. This could result in serving a "broken" page during Server-Side Rendering (SSR), or the build erroneously being marked as successful during Static Site Generation (SSG).Fixes #33642