diff --git a/packages/nextjs/src/config/wrappers/wrapperUtils.ts b/packages/nextjs/src/config/wrappers/wrapperUtils.ts index a66b4ee7c452..feca9cf4adb7 100644 --- a/packages/nextjs/src/config/wrappers/wrapperUtils.ts +++ b/packages/nextjs/src/config/wrappers/wrapperUtils.ts @@ -1,4 +1,6 @@ +import { captureException } from '@sentry/core'; import { getActiveTransaction } from '@sentry/tracing'; +import { Span } from '@sentry/types'; import { DataFetchingFunction } from './types'; @@ -31,11 +33,7 @@ export async function wrapperCore( // route's transaction const span = transaction.startChild({ op: 'nextjs.data', description: `${wrappedFunctionName} (${route})` }); - // TODO: Can't figure out how to tell TS that the types are correlated - that a `GSPropsFunction` will only get passed - // `GSPropsContext` and never, say, `GSSPContext`. That's what wrapping everything in objects and using the generic - // and pulling the types from the generic rather than specifying them directly was supposed to do, but... no luck. - // eslint-disable-next-line prefer-const, @typescript-eslint/no-explicit-any - const props = await (origFunction as any)(context); + const props = await callOriginal(origFunction, context, span); span.finish(); @@ -43,5 +41,25 @@ export async function wrapperCore( } // eslint-disable-next-line @typescript-eslint/no-explicit-any - return (origFunction as any)(context); + return callOriginal(origFunction, context); +} + +/** Call the original function, capturing any errors and finishing the span (if any) in case of error */ +async function callOriginal( + origFunction: T['fn'], + context: T['context'], + span?: Span, +): Promise { + try { + // eslint-disable-next-line prefer-const, @typescript-eslint/no-explicit-any + return (origFunction as any)(context); + } catch (err) { + if (span) { + span.finish(); + } + + // TODO Copy more robust error handling over from `withSentry` + captureException(err); + throw err; + } }