From 6cd283a07520b470c73894851d858240ac98aeb1 Mon Sep 17 00:00:00 2001 From: s1gr1d <32902192+s1gr1d@users.noreply.github.com> Date: Mon, 9 Feb 2026 10:33:47 +0100 Subject: [PATCH] fix(nextjs): Return correct `lastEventId` for SSR pages --- .../pages-router-instrumentation/_error.ts | 5 +++- .../captureUnderscoreErrorException.test.ts | 28 +++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/packages/nextjs/src/common/pages-router-instrumentation/_error.ts b/packages/nextjs/src/common/pages-router-instrumentation/_error.ts index 5f201dfa216b..22995c3eb839 100644 --- a/packages/nextjs/src/common/pages-router-instrumentation/_error.ts +++ b/packages/nextjs/src/common/pages-router-instrumentation/_error.ts @@ -1,4 +1,4 @@ -import { captureException, httpRequestToRequestData, withScope } from '@sentry/core'; +import { captureException, getIsolationScope, httpRequestToRequestData, withScope } from '@sentry/core'; import type { NextPageContext } from 'next'; import { flushSafelyWithTimeout, waitUntil } from '../utils/responseEnd'; @@ -57,6 +57,9 @@ export async function captureUnderscoreErrorException(contextOrProps: ContextOrP }); }); + // Set the lastEventId on the isolation scope so it's accessible via lastEventId() + getIsolationScope().setLastEventId(eventId); + waitUntil(flushSafelyWithTimeout()); return eventId; diff --git a/packages/nextjs/test/common/pages-router-instrumentation/captureUnderscoreErrorException.test.ts b/packages/nextjs/test/common/pages-router-instrumentation/captureUnderscoreErrorException.test.ts index 755ef8354b7c..c44083556276 100644 --- a/packages/nextjs/test/common/pages-router-instrumentation/captureUnderscoreErrorException.test.ts +++ b/packages/nextjs/test/common/pages-router-instrumentation/captureUnderscoreErrorException.test.ts @@ -1,6 +1,9 @@ +import { lastEventId } from '@sentry/core'; import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; import { captureUnderscoreErrorException } from '../../../src/common/pages-router-instrumentation/_error'; +let storedLastEventId: string | undefined = undefined; + const mockCaptureException = vi.fn(() => 'test-event-id'); const mockWithScope = vi.fn((callback: (scope: any) => any) => { const mockScope = { @@ -8,6 +11,13 @@ const mockWithScope = vi.fn((callback: (scope: any) => any) => { }; return callback(mockScope); }); +const mockLastEventId = vi.fn(() => storedLastEventId); +const mockGetIsolationScope = vi.fn(() => ({ + setLastEventId: (id: string | undefined) => { + storedLastEventId = id; + }, + lastEventId: () => storedLastEventId, +})); vi.mock('@sentry/core', async () => { const actual = await vi.importActual('@sentry/core'); @@ -16,6 +26,8 @@ vi.mock('@sentry/core', async () => { captureException: (...args: unknown[]) => mockCaptureException(...args), withScope: (callback: (scope: any) => any) => mockWithScope(callback), httpRequestToRequestData: vi.fn(() => ({ url: 'http://test.com' })), + lastEventId: () => mockLastEventId(), + getIsolationScope: () => mockGetIsolationScope(), }; }); @@ -27,6 +39,7 @@ vi.mock('../../../src/common/utils/responseEnd', () => ({ describe('captureUnderscoreErrorException', () => { beforeEach(() => { vi.clearAllMocks(); + storedLastEventId = undefined; }); afterEach(() => { @@ -114,4 +127,19 @@ describe('captureUnderscoreErrorException', () => { expect(result).toBeUndefined(); expect(mockCaptureException).not.toHaveBeenCalled(); }); + + it('lastEventId() should return the event ID after captureUnderscoreErrorException', async () => { + const error = new Error('Test error'); + const eventId = await captureUnderscoreErrorException({ + err: error, + pathname: '/test', + res: { statusCode: 500 } as any, + }); + + expect(eventId).toBe('test-event-id'); + expect(mockCaptureException).toHaveBeenCalled(); + + const lastId = lastEventId(); + expect(lastId).toBe('test-event-id'); + }); });