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 = (origHandler: NextApiHandler): WrappedNextApiHandler =
7676 try {
7777 return await origHandler ( req , res ) ;
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 , {
@@ -88,9 +94,14 @@ export const withSentry = (origHandler: NextApiHandler): WrappedNextApiHandler =
8894 } ) ;
8995 return event ;
9096 } ) ;
91- captureException ( e ) ;
97+
98+ captureException ( objectifiedErr ) ;
9299 }
93- throw e ;
100+
101+ // We rethrow here so that nextjs can do with the error whatever it would normally do. (Sometimes "whatever it
102+ // would normally do" is to allow the error to bubble up to the global handlers - another reason we need to mark
103+ // the error as already having been captured.)
104+ throw objectifiedErr ;
94105 }
95106 } ) ;
96107
0 commit comments