Skip to content

Commit 6cd283a

Browse files
committed
fix(nextjs): Return correct lastEventId for SSR pages
1 parent 11221d6 commit 6cd283a

File tree

2 files changed

+32
-1
lines changed

2 files changed

+32
-1
lines changed

packages/nextjs/src/common/pages-router-instrumentation/_error.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { captureException, httpRequestToRequestData, withScope } from '@sentry/core';
1+
import { captureException, getIsolationScope, httpRequestToRequestData, withScope } from '@sentry/core';
22
import type { NextPageContext } from 'next';
33
import { flushSafelyWithTimeout, waitUntil } from '../utils/responseEnd';
44

@@ -57,6 +57,9 @@ export async function captureUnderscoreErrorException(contextOrProps: ContextOrP
5757
});
5858
});
5959

60+
// Set the lastEventId on the isolation scope so it's accessible via lastEventId()
61+
getIsolationScope().setLastEventId(eventId);
62+
6063
waitUntil(flushSafelyWithTimeout());
6164

6265
return eventId;

packages/nextjs/test/common/pages-router-instrumentation/captureUnderscoreErrorException.test.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,23 @@
1+
import { lastEventId } from '@sentry/core';
12
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
23
import { captureUnderscoreErrorException } from '../../../src/common/pages-router-instrumentation/_error';
34

5+
let storedLastEventId: string | undefined = undefined;
6+
47
const mockCaptureException = vi.fn(() => 'test-event-id');
58
const mockWithScope = vi.fn((callback: (scope: any) => any) => {
69
const mockScope = {
710
setSDKProcessingMetadata: vi.fn(),
811
};
912
return callback(mockScope);
1013
});
14+
const mockLastEventId = vi.fn(() => storedLastEventId);
15+
const mockGetIsolationScope = vi.fn(() => ({
16+
setLastEventId: (id: string | undefined) => {
17+
storedLastEventId = id;
18+
},
19+
lastEventId: () => storedLastEventId,
20+
}));
1121

1222
vi.mock('@sentry/core', async () => {
1323
const actual = await vi.importActual('@sentry/core');
@@ -16,6 +26,8 @@ vi.mock('@sentry/core', async () => {
1626
captureException: (...args: unknown[]) => mockCaptureException(...args),
1727
withScope: (callback: (scope: any) => any) => mockWithScope(callback),
1828
httpRequestToRequestData: vi.fn(() => ({ url: 'http://test.com' })),
29+
lastEventId: () => mockLastEventId(),
30+
getIsolationScope: () => mockGetIsolationScope(),
1931
};
2032
});
2133

@@ -27,6 +39,7 @@ vi.mock('../../../src/common/utils/responseEnd', () => ({
2739
describe('captureUnderscoreErrorException', () => {
2840
beforeEach(() => {
2941
vi.clearAllMocks();
42+
storedLastEventId = undefined;
3043
});
3144

3245
afterEach(() => {
@@ -114,4 +127,19 @@ describe('captureUnderscoreErrorException', () => {
114127
expect(result).toBeUndefined();
115128
expect(mockCaptureException).not.toHaveBeenCalled();
116129
});
130+
131+
it('lastEventId() should return the event ID after captureUnderscoreErrorException', async () => {
132+
const error = new Error('Test error');
133+
const eventId = await captureUnderscoreErrorException({
134+
err: error,
135+
pathname: '/test',
136+
res: { statusCode: 500 } as any,
137+
});
138+
139+
expect(eventId).toBe('test-event-id');
140+
expect(mockCaptureException).toHaveBeenCalled();
141+
142+
const lastId = lastEventId();
143+
expect(lastId).toBe('test-event-id');
144+
});
117145
});

0 commit comments

Comments
 (0)