File tree Expand file tree Collapse file tree 3 files changed +51
-2
lines changed
dev-packages/e2e-tests/test-applications/nextjs-15
packages/nextjs/src/server Expand file tree Collapse file tree 3 files changed +51
-2
lines changed Original file line number Diff line number Diff line change 1+ import * as Sentry from '@sentry/nextjs' ;
2+ import { use } from 'react' ;
3+ export const dynamic = 'force-dynamic' ;
4+
5+ export default async function Page ( ) {
6+ try {
7+ use ( fetch ( 'http://example.com/' ) ) ;
8+ } catch ( e ) {
9+ Sentry . captureException ( e ) ; // This error should not be reported
10+ await new Promise ( resolve => setTimeout ( resolve , 1000 ) ) ; // Wait for any async event processors to run
11+ await Sentry . flush ( ) ;
12+ }
13+
14+ return < p > test</ p > ;
15+ }
Original file line number Diff line number Diff line change 1+ import { expect , test } from '@playwright/test' ;
2+ import { waitForError , waitForTransaction } from '@sentry-internal/event-proxy-server' ;
3+
4+ test ( 'should not capture serverside suspense errors' , async ( { page } ) => {
5+ const pageServerComponentTransactionPromise = waitForTransaction ( 'nextjs-15' , async transactionEvent => {
6+ return transactionEvent ?. transaction === 'Page Server Component (/suspense-error)' ;
7+ } ) ;
8+
9+ let errorEvent ;
10+ waitForError ( 'nextjs-15' , async transactionEvent => {
11+ return transactionEvent ?. transaction === 'Page Server Component (/suspense-error)' ;
12+ } ) . then ( event => {
13+ errorEvent = event ;
14+ } ) ;
15+
16+ await page . goto ( `/suspense-error` ) ;
17+
18+ await page . waitForTimeout ( 5000 ) ;
19+
20+ const pageServerComponentTransaction = await pageServerComponentTransactionPromise ;
21+ expect ( pageServerComponentTransaction ) . toBeDefined ( ) ;
22+
23+ expect ( errorEvent ) . toBeUndefined ( ) ;
24+ } ) ;
Original file line number Diff line number Diff line change @@ -190,13 +190,23 @@ export function init(options: NodeOptions): void {
190190
191191 const originalException = hint . originalException ;
192192
193- const isReactControlFlowError =
193+ const isPostponeError =
194194 typeof originalException === 'object' &&
195195 originalException !== null &&
196196 '$$typeof' in originalException &&
197197 originalException . $$typeof === Symbol . for ( 'react.postpone' ) ;
198198
199- if ( isReactControlFlowError ) {
199+ if ( isPostponeError ) {
200+ // Postpone errors are used for partial-pre-rendering (PPR)
201+ return null ;
202+ }
203+
204+ // We don't want to capture suspense errors as they are simply used by React/Next.js for control flow
205+ const exceptionMessage = event . exception ?. values ?. [ 0 ] ?. value ;
206+ if (
207+ exceptionMessage ?. includes ( 'Suspense Exception: This is not a real error!' ) ||
208+ exceptionMessage ?. includes ( 'Suspense Exception: This is not a real error, and should not leak' )
209+ ) {
200210 return null ;
201211 }
202212
You can’t perform that action at this time.
0 commit comments