From a46b72ec8e7601319d0fefc8708383dff0616b34 Mon Sep 17 00:00:00 2001 From: Vladimir Babin Date: Fri, 18 Sep 2026 10:27:18 +0300 Subject: [PATCH 1/2] fix(bun): Respect caller-supplied `runtime` option `@sentry/bun`'s `init` unconditionally overwrote `runtime` with a hard-coded Bun value, so SDKs wrapping it (`@sentry/elysia` on Node) reported `{ name: 'bun', version: 'unknown' }`. Only default the runtime when the caller did not provide one, matching `NodeClient`. Closes #24047 --- packages/bun/src/sdk.ts | 2 +- packages/bun/src/types.ts | 8 ++++++++ packages/bun/test/init.test.ts | 14 ++++++++++++++ packages/elysia/test/sdk.test.ts | 12 ++++++++++++ 4 files changed, 35 insertions(+), 1 deletion(-) diff --git a/packages/bun/src/sdk.ts b/packages/bun/src/sdk.ts index ba77f87ef9a9..2884cd542851 100644 --- a/packages/bun/src/sdk.ts +++ b/packages/bun/src/sdk.ts @@ -145,7 +145,7 @@ function _init( const options = { ...userOptions, platform: 'javascript', - runtime: { name: 'bun', version: typeof Bun !== 'undefined' ? Bun.version : 'unknown' }, + runtime: userOptions.runtime || { name: 'bun', version: typeof Bun !== 'undefined' ? Bun.version : 'unknown' }, serverName: userOptions.serverName || global.process.env.SENTRY_NAME || os.hostname(), }; diff --git a/packages/bun/src/types.ts b/packages/bun/src/types.ts index 34643a995ab1..ade64f83137f 100644 --- a/packages/bun/src/types.ts +++ b/packages/bun/src/types.ts @@ -21,6 +21,14 @@ export interface BaseBunOptions extends ServerRuntimeOptions { * @default false */ enableOpenTelemetrySetup?: boolean; + + /** + * Override the runtime name reported in events. + * Defaults to 'bun' with the current Bun version if not specified. + * + * @hidden This is primarily used internally to support SDKs wrapping the Bun SDK, like Elysia. + */ + runtime?: { name: string; version?: string }; } /** diff --git a/packages/bun/test/init.test.ts b/packages/bun/test/init.test.ts index abf3aabf060e..2fced80fd67a 100644 --- a/packages/bun/test/init.test.ts +++ b/packages/bun/test/init.test.ts @@ -129,6 +129,20 @@ describe('init()', () => { }); }); + describe('runtime', () => { + it('defaults to bun', () => { + init({ dsn: PUBLIC_DSN, traceLifecycle: 'static' }); + + expect(getClient()?.getOptions().runtime).toEqual({ name: 'bun', version: Bun.version }); + }); + + it('respects a runtime provided through options', () => { + init({ dsn: PUBLIC_DSN, traceLifecycle: 'static', runtime: { name: 'node', version: '20.0.0' } }); + + expect(getClient()?.getOptions().runtime).toEqual({ name: 'node', version: '20.0.0' }); + }); + }); + describe('initWithoutDefaultIntegrations()', () => { it('installs no default integrations', () => { initWithoutDefaultIntegrations({ dsn: PUBLIC_DSN, traceLifecycle: 'static' }); diff --git a/packages/elysia/test/sdk.test.ts b/packages/elysia/test/sdk.test.ts index d27011f0e416..dab3dd8f3575 100644 --- a/packages/elysia/test/sdk.test.ts +++ b/packages/elysia/test/sdk.test.ts @@ -108,6 +108,18 @@ describe('init', () => { expect(calledOptions.runtime.name).toBe('node'); expect(calledOptions.runtime.version).toBe(process.version); }); + + it('detects bun runtime when Bun is defined', () => { + vi.stubGlobal('Bun', { version: '1.2.3' }); + + init({ dsn: 'https://***@o0.ingest.sentry.io/0' }); + + const calledOptions = mockInitNode.mock.calls[0]![0]; + expect(calledOptions.runtime).toEqual({ name: 'bun', version: '1.2.3' }); + expect(mockApplySdkMetadata).toHaveBeenCalledWith(expect.anything(), 'elysia', ['elysia', 'bun']); + + vi.unstubAllGlobals(); + }); }); describe('getDefaultIntegrations', () => { From d4b65207fe72eac6495ebf1fe5c63a8bced7bb9d Mon Sep 17 00:00:00 2001 From: Vladimir Babin Date: Fri, 18 Sep 2026 13:32:16 +0300 Subject: [PATCH 2/2] test(elysia): move vi.unstubAllGlobals to afterEach Per review feedback: unstubbing inline at the end of the test means it is skipped if an assertion above it fails, leaking the stubbed `Bun` global into later tests. Move it into the existing `afterEach` so cleanup always runs. --- packages/elysia/test/sdk.test.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/elysia/test/sdk.test.ts b/packages/elysia/test/sdk.test.ts index dab3dd8f3575..142c3f4ff456 100644 --- a/packages/elysia/test/sdk.test.ts +++ b/packages/elysia/test/sdk.test.ts @@ -29,6 +29,7 @@ const { init, getDefaultIntegrations } = await import('../src/sdk'); describe('init', () => { afterEach(() => { vi.clearAllMocks(); + vi.unstubAllGlobals(); }); it('sets SDK metadata to elysia', () => { @@ -117,8 +118,6 @@ describe('init', () => { const calledOptions = mockInitNode.mock.calls[0]![0]; expect(calledOptions.runtime).toEqual({ name: 'bun', version: '1.2.3' }); expect(mockApplySdkMetadata).toHaveBeenCalledWith(expect.anything(), 'elysia', ['elysia', 'bun']); - - vi.unstubAllGlobals(); }); });