Skip to content

[bug] Elysia AsyncLocalStorage probe breaks bun:test lifecycle hooks #496

Description

@adrian-scehura

evlog version

2.24.0

Runtime & OS

Bun 1.3.14+0d9b296af and Bun 1.4.0-canary.1+52af83272, macOS arm64

Framework / integration

Elysia

Adapter or drain

None

Description

In evlog 2.24.0, Elysia’s shared AsyncLocalStorage initialization calls supportsAsyncLocalStorageEnterWith(). That function invokes storage.enterWith(undefined) as a capability probe, originally to detect runtimes such as Cloudflare Workers where the method exists but throws.

On Bun, enterWith() is implemented and does not throw. However, calling it during test initialization replaces the active async context used by bun:test. The test body completes, but lifecycle hooks subsequently time out.

Avoiding the enterWith(undefined) probe on Bun fixes the failure. The normal request-time calls to enterWith(logger) and cleanup remain functional.

The same behavior reproduces on the current Bun 1.4.0 canary.

Expected behavior

Importing or initializing the Elysia integration should not mutate the caller’s active AsyncLocalStorage context. Tests using evlog/elysia should complete their lifecycle hooks normally.

Cloudflare Workers should retain the existing fallback for runtimes where enterWith() throws.

Actual behavior

The test assertion completes, but afterEach is no longer completed by bun:test and times out after 10 seconds:

(fail) completes its lifecycle [10000.03ms]
^ a beforeEach/afterEach hook timed out before its done callback was called

0 pass
1 fail
1 expect() calls

Skipping the capability probe on Bun makes the test pass immediately. With that workaround applied, our complete server suite passes: 216 tests.

Reproduction

The following isolates the operation performed by evlog’s capability check:

import { AsyncLocalStorage } from "node:async_hooks";
import { afterEach, expect, test } from "bun:test";

const storage = new AsyncLocalStorage<unknown>();

// This is the capability probe performed during evlog initialization.
storage.enterWith(undefined);

afterEach(() => {});

test("completes its lifecycle", () => {
  expect(true).toBe(true);
});

Run:

bun test probe.test.ts

Tested with:

Bun 1.3.14+0d9b296af
Bun 1.4.0-canary.1+52af83272

Removing storage.enterWith(undefined) makes the test pass.

A possible defensive fix is to avoid this side-effecting capability probe when running under Bun, while retaining it for runtimes where enterWith() may be present but unimplemented.

Logs

bun test v1.4.0-canary.1 (52af83272)

probe.test.ts:
(fail) completes its lifecycle [10000.03ms]
  ^ a beforeEach/afterEach hook timed out before its done callback was called

0 pass
1 fail
1 expect() calls
Ran 1 test across 1 file. [10.01s]

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions