Skip to content

Conversation

@robobun
Copy link
Collaborator

@robobun robobun commented Jan 28, 2026

Summary

  • Fixed node:diagnostics_channel channels being garbage collected even when they have active subscribers
  • This was causing OpenTelemetry instrumentation to fail for frameworks like Fastify and Express when subscribers were registered in preload scripts

Root Cause

The WeakReference class in diagnostics_channel.ts extended WeakRef but only tracked a reference count without actually preventing garbage collection. When channels had active subscribers, they could still be GC'd because there was no strong reference keeping them alive.

Fix

Aligned the WeakReference implementation with Node.js by maintaining a strong reference when refCount > 0:

  • When incRef() is called and refCount transitions from 0 to 1, store a strong reference
  • When decRef() returns refCount to 0, clear the strong reference to allow GC

This matches the behavior in Node.js's internal util.js.

Test plan

  • Added regression test that verifies subscribers persist from preload to main script
  • Test covers both ESM and CJS preload scripts
  • Existing diagnostics_channel.test.ts tests pass
  • Verified test fails with system Bun (v1.3.7) and passes with debug build

Fixes #26536

🤖 Generated with Claude Code

@robobun
Copy link
Collaborator Author

robobun commented Jan 28, 2026

Updated 12:40 PM PT - Jan 28th, 2026

❌ Your commit 33b9a33b has 5 failures in Build #36021 (All Failures):


🧪   To try this PR locally:

bunx bun-pr 26537

That installs a local version of the PR into your bun-26537 executable, so you can run:

bun-26537 --bun

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 28, 2026

Walkthrough

WeakReference in diagnostics_channel.ts is refactored to compose a private WeakRef with an explicit strong-reference cache and reference counting; regression tests added to ensure diagnostics_channel subscribers persist across Bun preload and main app contexts.

Changes

Cohort / File(s) Summary
Reference lifecycle management
src/js/node/diagnostics_channel.ts
Replaced class WeakReference<T extends WeakKey> extends WeakRef<T> with a non‑extending class that holds #weak: WeakRef<T>, `#strong: T
Issue 26536 regression tests
test/regression/issue/26536.test.ts
Added three tests that spawn Bun with --preload to verify subscriber persistence and shared diagnostics_channel identity across preload and main app contexts: (1) ESM preload + ESM app, (2) CJS preload + ESM app, (3) preload stores channel on globalThis and app verifies identity.
🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The PR title clearly and concisely summarizes the main change: fixing diagnostics_channel to retain channels with active subscribers.
Description check ✅ Passed The PR description includes a clear summary of the fix, explains the root cause, describes the implementation approach with reference to Node.js behavior, and documents the test plan with verification steps.
Linked Issues check ✅ Passed The PR addresses issue #26536 by fixing WeakReference to maintain strong references while refCount > 0, ensuring diagnostics_channel subscribers persist across preload scripts, which directly resolves the OpenTelemetry instrumentation failures.
Out of Scope Changes check ✅ Passed All code changes are scoped to fixing the diagnostics_channel WeakReference implementation and adding regression tests for issue #26536; no unrelated or out-of-scope modifications are present.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@src/js/node/diagnostics_channel.ts`:
- Around line 23-33: The private field `#strong` is currently unused which
triggers the no-unused-private-class-members lint rule; update the get() method
to use `#strong` by grabbing the dereferenced value from `#weak` (via
this.#weak.deref()), assign it to this.#strong (and optionally update
this.#refCount if you want to track strong refs), then return the value — this
ensures `#strong` is read/written and keeps the existing `#weak`, `#strong`, get(),
and `#refCount` semantics intact.

The WeakReference class in diagnostics_channel was allowing channels to
be garbage collected even when they had active subscribers. This caused
subscribers registered in preload scripts to be lost when the main
application script ran, breaking OpenTelemetry instrumentation for
frameworks like Fastify and Express.

The fix aligns WeakReference behavior with Node.js by maintaining a
strong reference when refCount > 0. When incRef() is called and refCount
transitions from 0 to 1, a strong reference is stored. When decRef()
returns refCount to 0, the strong reference is cleared, allowing GC.

The get() method now returns the strong reference when available,
falling back to the weak reference otherwise.

Fixes #26536

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@robobun robobun force-pushed the claude/fix-diagnostics-channel-preload branch from 7e5414b to 33b9a33 Compare January 28, 2026 19:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bun doesn't work correctly with Open Telemetry express/fastify/http instrumentation

2 participants