-
Notifications
You must be signed in to change notification settings - Fork 26.3k
fix(platform-server): propagate errors from lifecycle hooks when utilizing platform-server #55787
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
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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 ErrorInterceptor
s 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
renderModule
andrenderApplication
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 #33642