Skip to content

Commit b8dd290

Browse files
authored
test(node): Add test demonstrating withIsolationScope data loss on uncaught errors (#16479)
This PR adds a test demonstrating the unintuitive but expected behaviour reported in #16460 see comment for more details
1 parent 8657ded commit b8dd290

File tree

4 files changed

+107
-1
lines changed

4 files changed

+107
-1
lines changed

dev-packages/node-integration-tests/suites/express-v5/handle-error-scope-data-loss/server.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,13 @@ app.get('/test/isolationScope', () => {
2525
throw new Error('isolation_test_error');
2626
});
2727

28+
app.get('/test/withIsolationScope', () => {
29+
Sentry.withIsolationScope(iScope => {
30+
iScope.setTag('with-isolation-scope', 'tag');
31+
throw new Error('with_isolation_scope_test_error');
32+
});
33+
});
34+
2835
Sentry.setupExpressErrorHandler(app);
2936

3037
startExpressServerAndSendPortToRunner(app);

dev-packages/node-integration-tests/suites/express-v5/handle-error-scope-data-loss/test.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,3 +86,49 @@ test('isolation scope is applied to thrown error caught by global handler', asyn
8686
runner.makeRequest('get', '/test/isolationScope', { expectError: true });
8787
await runner.completed();
8888
});
89+
90+
/**
91+
* This test shows that an inner isolation scope, created via `withIsolationScope`, is not applied to the error.
92+
*
93+
* This behaviour occurs because, just like in the test above where we use `getIsolationScope().setTag`,
94+
* this isolation scope again is only valid as long as we're in the callback.
95+
*
96+
* So why _does_ the http isolation scope get applied then? Because express' error handler applies on
97+
* a per-request basis, meaning, it's called while we're inside the isolation scope of the http request,
98+
* created from our `httpIntegration`.
99+
*/
100+
test('withIsolationScope scope is NOT applied to thrown error caught by global handler', async () => {
101+
const runner = createRunner(__dirname, 'server.ts')
102+
.expect({
103+
event: {
104+
exception: {
105+
values: [
106+
{
107+
mechanism: {
108+
type: 'middleware',
109+
handled: false,
110+
},
111+
type: 'Error',
112+
value: 'with_isolation_scope_test_error',
113+
stacktrace: {
114+
frames: expect.arrayContaining([
115+
expect.objectContaining({
116+
function: expect.any(String),
117+
lineno: expect.any(Number),
118+
colno: expect.any(Number),
119+
}),
120+
]),
121+
},
122+
},
123+
],
124+
},
125+
// 'with-isolation-scope' tag is not applied to the event
126+
tags: expect.not.objectContaining({ 'with-isolation-scope': expect.anything() }),
127+
},
128+
})
129+
.start();
130+
131+
runner.makeRequest('get', '/test/withIsolationScope', { expectError: true });
132+
133+
await runner.completed();
134+
});

dev-packages/node-integration-tests/suites/express/handle-error-scope-data-loss/server.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,13 @@ app.get('/test/isolationScope', () => {
2525
throw new Error('isolation_test_error');
2626
});
2727

28+
app.get('/test/withIsolationScope', () => {
29+
Sentry.withIsolationScope(iScope => {
30+
iScope.setTag('with-isolation-scope', 'tag');
31+
throw new Error('with_isolation_scope_test_error');
32+
});
33+
});
34+
2835
Sentry.setupExpressErrorHandler(app);
2936

3037
startExpressServerAndSendPortToRunner(app);

dev-packages/node-integration-tests/suites/express/handle-error-scope-data-loss/test.ts

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ test('withScope scope is NOT applied to thrown error caught by global handler',
5353
/**
5454
* This test shows that the isolation scope set tags are applied correctly to the error.
5555
*/
56-
test('isolation scope is applied to thrown error caught by global handler', async () => {
56+
test('http requestisolation scope is applied to thrown error caught by global handler', async () => {
5757
const runner = createRunner(__dirname, 'server.ts')
5858
.expect({
5959
event: {
@@ -90,3 +90,49 @@ test('isolation scope is applied to thrown error caught by global handler', asyn
9090

9191
await runner.completed();
9292
});
93+
94+
/**
95+
* This test shows that an inner isolation scope, created via `withIsolationScope`, is not applied to the error.
96+
*
97+
* This behaviour occurs because, just like in the test above where we use `getIsolationScope().setTag`,
98+
* this isolation scope again is only valid as long as we're in the callback.
99+
*
100+
* So why _does_ the http isolation scope get applied then? Because express' error handler applies on
101+
* a per-request basis, meaning, it's called while we're inside the isolation scope of the http request,
102+
* created from our `httpIntegration`.
103+
*/
104+
test('withIsolationScope scope is NOT applied to thrown error caught by global handler', async () => {
105+
const runner = createRunner(__dirname, 'server.ts')
106+
.expect({
107+
event: {
108+
exception: {
109+
values: [
110+
{
111+
mechanism: {
112+
type: 'middleware',
113+
handled: false,
114+
},
115+
type: 'Error',
116+
value: 'with_isolation_scope_test_error',
117+
stacktrace: {
118+
frames: expect.arrayContaining([
119+
expect.objectContaining({
120+
function: expect.any(String),
121+
lineno: expect.any(Number),
122+
colno: expect.any(Number),
123+
}),
124+
]),
125+
},
126+
},
127+
],
128+
},
129+
// 'with-isolation-scope' tag is not applied to the event
130+
tags: expect.not.objectContaining({ 'with-isolation-scope': expect.anything() }),
131+
},
132+
})
133+
.start();
134+
135+
runner.makeRequest('get', '/test/withIsolationScope', { expectError: true });
136+
137+
await runner.completed();
138+
});

0 commit comments

Comments
 (0)