From f05d6c55faf3dcb97939849479a7f5e02e44d24f Mon Sep 17 00:00:00 2001 From: Nicolas Hrubec Date: Mon, 4 May 2026 11:53:39 +0200 Subject: [PATCH] fix(core): Guard against undefined `chained` in `copyProps` Non-standard thenables (e.g. Fastify reply objects) can return `undefined` from `.then()`, causing a `TypeError` in `copyProps` when using the `in` operator on `undefined`. Return the original object as fallback. Closes https://github.com/getsentry/sentry-javascript/issues/20623 Co-Authored-By: Claude Opus 4.6 (1M context) --- .../src/utils/chain-and-copy-promiselike.ts | 1 + .../utils/chain-and-copy-promiselike.test.ts | 21 +++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/packages/core/src/utils/chain-and-copy-promiselike.ts b/packages/core/src/utils/chain-and-copy-promiselike.ts index 4d8db088d22e..ea04d77e015e 100644 --- a/packages/core/src/utils/chain-and-copy-promiselike.ts +++ b/packages/core/src/utils/chain-and-copy-promiselike.ts @@ -32,6 +32,7 @@ export const chainAndCopyPromiseLike = >( // eslint-disable-next-line @typescript-eslint/no-explicit-any const copyProps = >(original: T, chained: T): T => { + if (!chained) return original; let mutated = false; //oxlint-disable-next-line guard-for-in for (const key in original) { diff --git a/packages/core/test/lib/utils/chain-and-copy-promiselike.test.ts b/packages/core/test/lib/utils/chain-and-copy-promiselike.test.ts index 2f4415940dc8..d357ffd9bb34 100644 --- a/packages/core/test/lib/utils/chain-and-copy-promiselike.test.ts +++ b/packages/core/test/lib/utils/chain-and-copy-promiselike.test.ts @@ -53,4 +53,25 @@ describe('chain and copy promiselike objects', () => { expect(success).toBe(true); expect(error).toBe(false); }); + + it('returns original when .then() returns undefined', () => { + const original = { + value: 42, + then() { + return undefined; + }, + customMethod() { + return 'hello'; + }, + } as unknown as PromiseLike & { customMethod: () => string }; + + const q = chainAndCopyPromiseLike( + original, + () => {}, + () => {}, + ); + + expect(q).toBe(original); + expect((q as typeof original).customMethod()).toBe('hello'); + }); });