11import { captureException , flush , getCurrentHub , Handlers , startTransaction } from '@sentry/node' ;
22import { extractTraceparentData , hasTracingEnabled } from '@sentry/tracing' ;
33import { Transaction } from '@sentry/types' ;
4- import { addExceptionMechanism , isString , logger , stripUrlQueryAndFragment } from '@sentry/utils' ;
4+ import { addExceptionMechanism , isString , logger , objectify , stripUrlQueryAndFragment } from '@sentry/utils' ;
55import * as domain from 'domain' ;
66import { NextApiHandler , NextApiResponse } from 'next' ;
77
@@ -76,6 +76,12 @@ export const withSentry = (handler: NextApiHandler): WrappedNextApiHandler => {
7676 try {
7777 return await handler ( req , res ) ; // Call original handler
7878 } catch ( e ) {
79+ // In case we have a primitive, wrap it in the equivalent wrapper class (string -> String, etc.) so that we can
80+ // store a seen flag on it. (Because of the one-way-on-Vercel-one-way-off-of-Vercel approach we've been forced
81+ // to take, it can happen that the same thrown object gets caught in two different ways, and flagging it is a
82+ // way to prevent it from actually being reported twice.)
83+ const objectifiedErr = objectify ( e ) ;
84+
7985 if ( currentScope ) {
8086 currentScope . addEventProcessor ( event => {
8187 addExceptionMechanism ( event , {
@@ -84,9 +90,14 @@ export const withSentry = (handler: NextApiHandler): WrappedNextApiHandler => {
8490 } ) ;
8591 return event ;
8692 } ) ;
87- captureException ( e ) ;
93+
94+ captureException ( objectifiedErr ) ;
8895 }
89- throw e ;
96+
97+ // We rethrow here so that nextjs can do with the error whatever it would normally do. (Sometimes "whatever it
98+ // would normally do" is to allow the error to bubble up to the global handlers - another reason we need to mark
99+ // the error as already having been captured.)
100+ throw objectifiedErr ;
90101 }
91102 } ) ;
92103
0 commit comments