Uh oh!
There was an error while loading. Please reload this page.
fix(nextjs): Delay error propagation until withSentry is done - #4027
Conversation
size-limit report
|
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
54db08b to
5d1ad31Comparejoshsny
commented
Nov 4, 2021
Thank you for this PR 🙏 Is this likely to get merged soon? This is a big issue right now, with no monitoring on our production apps routes deployed to Vercel. If not, it would be great to update the docs of @sentry/nextjs saying that it does not work on Vercel. |
5d1ad31 to
1bb2edbCompare
iker-barriocanal
left a comment
There was a problem hiding this comment.
Blocking because of an infinte loop in a test.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
1bb2edb to
5c89c28CompareUh oh!
There was an error while loading. Please reload this page.
| const captureExceptionSpy = jest.spyOn(Sentry, 'captureException').mockImplementation(jest.fn()); | ||
| const loggerSpy = jest.spyOn(utils.logger, 'log'); | ||
| const flushSpy = jest.spyOn(Sentry, 'flush').mockImplementation(async () => { | ||
| // simulate the time it takes time to flush all events |
There was a problem hiding this comment.
| // simulate the time it takes time to flush all events | |
| // simulate the time it takes to flush all events |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
lobsterkatie
commented
Nov 15, 2021
Discussed IRL - agreed to merge this. |
In our nextjs API route wrapper `withSentry`, we capture any errors thrown by the original handler, and then once we've captured them, we rethrow them, so that our capturing of them doesn't interfere with whatever other error handling might go on. Until recently, that was fine, as nextjs didn't actually propagate the error any farther, and so it didn't interfere with our processing pipeline and didn't prevent `res.end()` (on which we rely for finishing the transaction and flushing events to Sentry) from running. However, Vercel released a change[1] which caused said errors to begin propagating if the API route is running on Vercel. (Technically, it's if the server is running in minimal mode, but all API handlers on vercel do.) A side effect of this change is that when there's an error, `res.end()` is no longer called. As a result, the SDK's work is cut short, and neither errors in API route handlers nor transactions tracing such routes make it to Sentry. This fixes that, by moving the work of finishing the transaction and flushing events into its own function and calling it not only in `res.end()` but also before we rethrow the error. (Note: In the cases where there is an error and the server is not running in minimal mode, this means that function will be hit twice, but that's okay, since the second time around it will just no-op, since `transaction.finish()` bails immediately if the transaction is already finished, and `flush()` returns immediately if there's nothing to flush.) H/t to @jmurty for his work in #4044, which helped me fix some problems in my first approach to solving this problem. Fixes#3917. [1] vercel/next.js#26875
In our nextjs API route wrapper `withSentry`, we capture any errors thrown by the original handler, and then once we've captured them, we rethrow them, so that our capturing of them doesn't interfere with whatever other error handling might go on. Until recently, that was fine, as nextjs didn't actually propagate the error any farther, and so it didn't interfere with our processing pipeline and didn't prevent `res.end()` (on which we rely for finishing the transaction and flushing events to Sentry) from running. However, Vercel released a change[1] which caused said errors to begin propagating if the API route is running on Vercel. (Technically, it's if the server is running in minimal mode, but all API handlers on vercel do.) A side effect of this change is that when there's an error, `res.end()` is no longer called. As a result, the SDK's work is cut short, and neither errors in API route handlers nor transactions tracing such routes make it to Sentry. This fixes that, by moving the work of finishing the transaction and flushing events into its own function and calling it not only in `res.end()` but also before we rethrow the error. (Note: In the cases where there is an error and the server is not running in minimal mode, this means that function will be hit twice, but that's okay, since the second time around it will just no-op, since `transaction.finish()` bails immediately if the transaction is already finished, and `flush()` returns immediately if there's nothing to flush.) H/t to @jmurty for his work in #4044, which helped me fix some problems in my first approach to solving this problem. Fixes#3917. [1] vercel/next.js#26875
In our nextjs API route wrapper
withSentry, we capture any errors thrown by the original handler, and then once we've captured them, we rethrow them, so that our capturing of them doesn't interfere with whatever other error handling might go on. Until recently, that was fine, as nextjs didn't actually propagate the error any farther, and so it didn't interfere with our processing pipeline and didn't preventres.end()(on which we rely for finishing the transaction and flushing events to Sentry) from running.However, Vercel released a change which caused said errors to begin propagating if the API route is running on Vercel. (Technically, it's if the server is running in minimal mode, but all API handlers on vercel do.) A side effect of this change is that when there's an error,
res.end()is no longer called. As a result, the SDK's work is cut short, and neither errors in API route handlers nor transactions tracing such routes make it to Sentry.This fixes that, by moving the work of finishing the transaction and flushing events into its own function and calling it not only in
res.end()but also before we rethrow the error.(Note: In the cases where there is an error and the server is not running in minimal mode, this means that function will be hit twice, but that's okay, since the second time around it will just no-op, since
transaction.finish()bails immediately if the transaction is already finished, andflush()returns immediately if there's nothing to flush.)H/t to @jmurty for his work in #4044, which helped me fix some problems in my first approach to solving this problem.
Fixes#3917.