From 059c30580b094588f6c144301c67543d21fab50a Mon Sep 17 00:00:00 2001 From: JPeer264 Date: Thu, 15 Jan 2026 17:53:48 +0100 Subject: [PATCH 1/3] test(fastify): Verify if upstream error is fixed and won't regress --- .../node-fastify-5/package.json | 2 +- .../playwright.override.config.mjs | 2 +- .../src/app-handle-error-override.ts | 20 +++++++++++++++++++ .../node-fastify-5/tests/errors.test.ts | 20 ++++++++++++++++++- 4 files changed, 41 insertions(+), 3 deletions(-) diff --git a/dev-packages/e2e-tests/test-applications/node-fastify-5/package.json b/dev-packages/e2e-tests/test-applications/node-fastify-5/package.json index e25531d0f575..a7a754d3f1a6 100644 --- a/dev-packages/e2e-tests/test-applications/node-fastify-5/package.json +++ b/dev-packages/e2e-tests/test-applications/node-fastify-5/package.json @@ -15,7 +15,7 @@ "dependencies": { "@sentry/node": "latest || *", "@types/node": "^18.19.1", - "fastify": "5.3.2", + "fastify": "^5.7.0", "typescript": "5.6.3", "ts-node": "10.9.2" }, diff --git a/dev-packages/e2e-tests/test-applications/node-fastify-5/playwright.override.config.mjs b/dev-packages/e2e-tests/test-applications/node-fastify-5/playwright.override.config.mjs index 31f2b913b58b..ee1f461c57c8 100644 --- a/dev-packages/e2e-tests/test-applications/node-fastify-5/playwright.override.config.mjs +++ b/dev-packages/e2e-tests/test-applications/node-fastify-5/playwright.override.config.mjs @@ -1,7 +1,7 @@ import { getPlaywrightConfig } from '@sentry-internal/test-utils'; const config = getPlaywrightConfig({ - startCommand: `pnpm start`, + startCommand: `pnpm start:override`, }); export default config; diff --git a/dev-packages/e2e-tests/test-applications/node-fastify-5/src/app-handle-error-override.ts b/dev-packages/e2e-tests/test-applications/node-fastify-5/src/app-handle-error-override.ts index 217201332e17..462f1520cb0a 100644 --- a/dev-packages/e2e-tests/test-applications/node-fastify-5/src/app-handle-error-override.ts +++ b/dev-packages/e2e-tests/test-applications/node-fastify-5/src/app-handle-error-override.ts @@ -48,6 +48,11 @@ Sentry.setupFastifyErrorHandler(app, { return false; } + // @ts-ignore // Fastify V5 is not typed correctly + if (_request.routeOptions?.url?.includes('/test-error-ignored') && _reply.statusCode === 500) { + return false; + } + return true; }, }); @@ -130,6 +135,21 @@ app.get('/test-outgoing-http-external-disallowed', async function (req, res) { res.send(data); }); +// Regression test for https://github.com/fastify/fastify/issues/6409 +// The error diagnostic channel was always sending 200 unless explicitly changed. +// This was fixed in Fastify 5.7.0 +app.register((childApp: F.FastifyInstance, _options: F.FastifyPluginOptions, next: (err?: Error) => void) => { + childApp.setErrorHandler((error: Error, _request: F.FastifyRequest, reply: F.FastifyReply) => { + reply.send({ ok: false }); + }); + + childApp.get('/test-error-ignored', async function () { + throw new Error('This is an error that will not be captured'); + }); + + next(); +}); + app.post('/test-post', function (req, res) { res.send({ status: 'ok', body: req.body }); }); diff --git a/dev-packages/e2e-tests/test-applications/node-fastify-5/tests/errors.test.ts b/dev-packages/e2e-tests/test-applications/node-fastify-5/tests/errors.test.ts index a25f990748ea..9bdcdc7de73d 100644 --- a/dev-packages/e2e-tests/test-applications/node-fastify-5/tests/errors.test.ts +++ b/dev-packages/e2e-tests/test-applications/node-fastify-5/tests/errors.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForError } from '@sentry-internal/test-utils'; +import { waitForError, waitForTransaction } from '@sentry-internal/test-utils'; test('Sends correct error event', async ({ baseURL }) => { const errorEventPromise = waitForError('node-fastify-5', event => { @@ -48,3 +48,21 @@ test('Does not send error when shouldHandleError returns false', async ({ baseUR // wait for a short time to ensure the error is not captured await new Promise(resolve => setTimeout(resolve, 1000)); }); + +// Regression test for https://github.com/fastify/fastify/issues/6409 +// The error diagnostic channel was always sending 200 unless explicitly changed. +// This was fixed in Fastify 5.7.0 +test('Error in child plugin with rethrown error handler reports correct 500 status', async ({ baseURL }) => { + const errorEventPromise = waitForError('node-fastify-5', event => { + return !event.type && event.exception?.values?.[0]?.value === 'This is an error that will not be captured'; + }); + + errorEventPromise.then(() => { + throw new Error('This error should not be captured'); + }); + + await fetch(`${baseURL}/test-error-ignored`); + + // wait for a short time to ensure the error is not captured + await new Promise(resolve => setTimeout(resolve, 1000)); +}); From 958d9c01ca16edc4e8e83e5b055e834e316202a0 Mon Sep 17 00:00:00 2001 From: JPeer264 Date: Fri, 16 Jan 2026 10:48:59 +0100 Subject: [PATCH 2/3] fixup! test(fastify): Verify if upstream error is fixed and won't regress --- .../node-fastify-5/src/app.ts | 25 ++++++++++++ .../node-fastify-5/tests/errors.test.ts | 40 +++++++++++++------ 2 files changed, 53 insertions(+), 12 deletions(-) diff --git a/dev-packages/e2e-tests/test-applications/node-fastify-5/src/app.ts b/dev-packages/e2e-tests/test-applications/node-fastify-5/src/app.ts index 83f7e53a45ce..610a42f6fc00 100644 --- a/dev-packages/e2e-tests/test-applications/node-fastify-5/src/app.ts +++ b/dev-packages/e2e-tests/test-applications/node-fastify-5/src/app.ts @@ -25,6 +25,11 @@ Sentry.init({ return false; } + // @ts-ignore // Fastify V5 is not typed correctly + if (_request.routeOptions?.url?.includes('/test-error-ignored') && _reply.statusCode === 500) { + return false; + } + return true; }, }), @@ -90,6 +95,21 @@ app.get('/test-error', async function (req, res) { res.send({ exceptionId }); }); +// Regression test for https://github.com/fastify/fastify/issues/6409 +// The error diagnostic channel was always sending 200 unless explicitly changed. +// This was fixed in Fastify 5.7.0 +app.register((childApp: F.FastifyInstance, _options: F.FastifyPluginOptions, next: (err?: Error) => void) => { + childApp.setErrorHandler((error: Error, _request: F.FastifyRequest, reply: F.FastifyReply) => { + reply.send({ ok: false }); + }); + + childApp.get('/test-error-ignored', async function () { + throw new Error('This is an error that will not be captured'); + }); + + next(); +}); + app.get('/test-error-not-captured', async function () { // This error will not be captured by Sentry throw new Error('This is an error that will not be captured'); @@ -127,6 +147,11 @@ app.post('/test-post', function (req, res) { res.send({ status: 'ok', body: req.body }); }); +app.get('/flush', async function (_req, res) { + await Sentry.flush(); + res.send({ ok: true }); +}); + app.listen({ port: port }); // A second app so we can test header propagation between external URLs diff --git a/dev-packages/e2e-tests/test-applications/node-fastify-5/tests/errors.test.ts b/dev-packages/e2e-tests/test-applications/node-fastify-5/tests/errors.test.ts index 9bdcdc7de73d..ae04e75564cc 100644 --- a/dev-packages/e2e-tests/test-applications/node-fastify-5/tests/errors.test.ts +++ b/dev-packages/e2e-tests/test-applications/node-fastify-5/tests/errors.test.ts @@ -35,34 +35,50 @@ test('Sends correct error event', async ({ baseURL }) => { }); test('Does not send error when shouldHandleError returns false', async ({ baseURL }) => { - const errorEventPromise = waitForError('node-fastify-5', event => { - return !event.type && event.exception?.values?.[0]?.value === 'This is an error that will not be captured'; + let errorEventOccurred = false; + + waitForError('node-fastify-5', event => { + if (!event.type && event.exception?.values?.[0]?.value === 'This is an error that will not be captured') { + errorEventOccurred = true; + } + return event?.transaction === 'GET /test-error-not-captured'; }); - errorEventPromise.then(() => { - throw new Error('This error should not be captured'); + const transactionEventPromise = waitForTransaction('node-fastify-5', transactionEvent => { + return transactionEvent?.transaction === 'GET /test-error-not-captured'; }); await fetch(`${baseURL}/test-error-not-captured`); - // wait for a short time to ensure the error is not captured - await new Promise(resolve => setTimeout(resolve, 1000)); + await transactionEventPromise; + + await fetch(`${baseURL}/flush`); + + expect(errorEventOccurred).toBe(false); }); // Regression test for https://github.com/fastify/fastify/issues/6409 // The error diagnostic channel was always sending 200 unless explicitly changed. // This was fixed in Fastify 5.7.0 test('Error in child plugin with rethrown error handler reports correct 500 status', async ({ baseURL }) => { - const errorEventPromise = waitForError('node-fastify-5', event => { - return !event.type && event.exception?.values?.[0]?.value === 'This is an error that will not be captured'; + let errorEventOccurred = false; + + waitForError('node-fastify-5', event => { + if (!event.type && event.exception?.values?.[0]?.value === 'This is an error that will not be captured') { + errorEventOccurred = true; + } + return event?.transaction === 'GET /test-error-ignored'; }); - errorEventPromise.then(() => { - throw new Error('This error should not be captured'); + const transactionEventPromise = waitForTransaction('node-fastify-5', transactionEvent => { + return transactionEvent?.transaction === 'GET /test-error-ignored'; }); await fetch(`${baseURL}/test-error-ignored`); - // wait for a short time to ensure the error is not captured - await new Promise(resolve => setTimeout(resolve, 1000)); + await transactionEventPromise; + + await fetch(`${baseURL}/flush`); + + expect(errorEventOccurred).toBe(false); }); From 6261b6b0f7105902b5dc18d698eaa06e4e97ea78 Mon Sep 17 00:00:00 2001 From: JPeer264 Date: Mon, 19 Jan 2026 09:46:56 +0100 Subject: [PATCH 3/3] fixup! test(fastify): Verify if upstream error is fixed and won't regress --- .../node-fastify-5/src/app-handle-error-override.ts | 5 +++++ .../node-fastify-5/tests/errors.test.ts | 12 ++++++++---- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/dev-packages/e2e-tests/test-applications/node-fastify-5/src/app-handle-error-override.ts b/dev-packages/e2e-tests/test-applications/node-fastify-5/src/app-handle-error-override.ts index 462f1520cb0a..91f0353816bb 100644 --- a/dev-packages/e2e-tests/test-applications/node-fastify-5/src/app-handle-error-override.ts +++ b/dev-packages/e2e-tests/test-applications/node-fastify-5/src/app-handle-error-override.ts @@ -154,6 +154,11 @@ app.post('/test-post', function (req, res) { res.send({ status: 'ok', body: req.body }); }); +app.get('/flush', async function (_req, res) { + await Sentry.flush(); + res.send({ ok: true }); +}); + app.listen({ port: port }); // A second app so we can test header propagation between external URLs diff --git a/dev-packages/e2e-tests/test-applications/node-fastify-5/tests/errors.test.ts b/dev-packages/e2e-tests/test-applications/node-fastify-5/tests/errors.test.ts index ae04e75564cc..8699b26d490b 100644 --- a/dev-packages/e2e-tests/test-applications/node-fastify-5/tests/errors.test.ts +++ b/dev-packages/e2e-tests/test-applications/node-fastify-5/tests/errors.test.ts @@ -48,12 +48,14 @@ test('Does not send error when shouldHandleError returns false', async ({ baseUR return transactionEvent?.transaction === 'GET /test-error-not-captured'; }); - await fetch(`${baseURL}/test-error-not-captured`); + const response = await fetch(`${baseURL}/test-error-not-captured`); await transactionEventPromise; - await fetch(`${baseURL}/flush`); + const flushResponse = await fetch(`${baseURL}/flush`); + expect(response.status).toBe(500); + expect(flushResponse.status).toBe(200); expect(errorEventOccurred).toBe(false); }); @@ -74,11 +76,13 @@ test('Error in child plugin with rethrown error handler reports correct 500 stat return transactionEvent?.transaction === 'GET /test-error-ignored'; }); - await fetch(`${baseURL}/test-error-ignored`); + const response = await fetch(`${baseURL}/test-error-ignored`); await transactionEventPromise; - await fetch(`${baseURL}/flush`); + const flushResponse = await fetch(`${baseURL}/flush`); + expect(response.status).toBe(500); + expect(flushResponse.status).toBe(200); expect(errorEventOccurred).toBe(false); });