From e276461eeaaa6a1cbda387059907e994e4808463 Mon Sep 17 00:00:00 2001 From: Lukas Stracke Date: Mon, 2 Sep 2024 10:08:03 +0200 Subject: [PATCH 1/2] fix(cloudflare): Guard `context.waitUntil` call in request handler --- packages/cloudflare/src/request.ts | 2 +- packages/cloudflare/test/request.test.ts | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/packages/cloudflare/src/request.ts b/packages/cloudflare/src/request.ts index 560c17afb9e7..e42e92ad1b22 100644 --- a/packages/cloudflare/src/request.ts +++ b/packages/cloudflare/src/request.ts @@ -89,7 +89,7 @@ export function wrapRequestHandler( captureException(e, { mechanism: { handled: false, type: 'cloudflare' } }); throw e; } finally { - context.waitUntil(flush(2000)); + context?.waitUntil(flush(2000)); } }, ); diff --git a/packages/cloudflare/test/request.test.ts b/packages/cloudflare/test/request.test.ts index 93764a292ab4..5218e8afe20b 100644 --- a/packages/cloudflare/test/request.test.ts +++ b/packages/cloudflare/test/request.test.ts @@ -45,6 +45,15 @@ describe('withSentry', () => { expect(context.waitUntil).toHaveBeenLastCalledWith(expect.any(Promise)); }); + test("doesn't error if context is undefined", () => { + expect(() => + wrapRequestHandler( + { options: MOCK_OPTIONS, request: new Request('https://example.com'), context: undefined as any }, + () => new Response('test'), + ), + ).not.toThrow(); + }); + test('creates a cloudflare client and sets it on the handler', async () => { const initAndBindSpy = vi.spyOn(SentryCore, 'initAndBind'); await wrapRequestHandler( From c4143d1b0d8f669ed783d8d6516aadb56428755c Mon Sep 17 00:00:00 2001 From: Lukas Stracke Date: Mon, 2 Sep 2024 10:52:59 +0200 Subject: [PATCH 2/2] adjust internal typing --- packages/cloudflare/src/request.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/cloudflare/src/request.ts b/packages/cloudflare/src/request.ts index e42e92ad1b22..7a474c3b27cb 100644 --- a/packages/cloudflare/src/request.ts +++ b/packages/cloudflare/src/request.ts @@ -31,7 +31,13 @@ export function wrapRequestHandler( handler: (...args: unknown[]) => Response | Promise, ): Promise { return withIsolationScope(async isolationScope => { - const { options, request, context } = wrapperOptions; + const { options, request } = wrapperOptions; + + // In certain situations, the passed context can become undefined. + // For example, for Astro while prerendering pages at build time. + // see: https://github.com/getsentry/sentry-javascript/issues/13217 + const context = wrapperOptions.context as ExecutionContext | undefined; + const client = init(options); isolationScope.setClient(client);