fix(http): fix Strong reference leak in server response streaming#25965
Conversation
When proxying streaming responses through Bun's HTTP server, a Strong reference leak occurred in RequestContext.doRenderWithBody(). The issue happened when: 1. A streaming response body was received (e.g., from a proxied fetch) 2. The response_body_readable_stream_ref was initialized (line 1836 or 1841) 3. For .Bytes streams with has_received_last_chunk=false, a new Strong reference was created (line 1902) without deinit'ing the old one This caused the Strong.Impl memory to leak on every streaming response, accumulating over time. The fix adds a deinit() call before creating the new Strong reference. This is safe because the stream variable exists as a stack-local variable and JSC's conservative GC tracks stack-local JSValues, so there's no risk of the stream being collected between deinit and the new Strong.init(). Similar to the fixes in #23313 and #25846 for fetch-related Strong ref leaks. Claude-Generated-By: Claude Code (cli/claude-opus-4-5=100%) Claude-Steers: 6 Claude-Permission-Prompts: 3 Claude-Escapes: 0
|
Updated 7:52 AM PT - Jan 11th, 2026
❌ @sosukesuzuki, your commit 2a9cf55 has 3 failures in
🧪 To try this PR locally: bunx bun-pr 25965That installs a local version of the PR into your bun-25965 --bun |
WalkthroughFixes memory leaks in RequestContext.zig by deinitializing existing Strong references to response_body_readable_stream before reassignment. Adds a test validating that proxy-forwarding streaming responses does not leak ReadableStream or Response objects. Changes
Possibly related PRs
Suggested reviewers
🚥 Pre-merge checks | ✅ 2✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. 📜 Recent review detailsConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Disabled knowledge base sources:
📒 Files selected for processing (2)
🧰 Additional context used📓 Path-based instructions (5)**/*.zig📄 CodeRabbit inference engine (CLAUDE.md)
Files:
src/**/*.zig📄 CodeRabbit inference engine (src/CLAUDE.md)
Files:
**/*.test.ts?(x)📄 CodeRabbit inference engine (CLAUDE.md)
Files:
test/**/*.test.ts?(x)📄 CodeRabbit inference engine (CLAUDE.md)
Files:
test/**/*.test.{ts,js,jsx,tsx,mjs,cjs}📄 CodeRabbit inference engine (test/CLAUDE.md)
Files:
🧠 Learnings (19)📓 Common learnings📚 Learning: 2025-10-18T20:59:45.579ZApplied to files:
📚 Learning: 2026-01-05T16:32:07.551ZApplied to files:
📚 Learning: 2025-10-19T04:55:33.099ZApplied to files:
📚 Learning: 2025-11-24T18:36:59.706ZApplied to files:
📚 Learning: 2025-10-18T05:23:24.403ZApplied to files:
📚 Learning: 2026-01-05T23:04:01.518ZApplied to files:
📚 Learning: 2025-10-20T01:38:02.660ZApplied to files:
📚 Learning: 2025-10-26T01:32:04.844ZApplied to files:
📚 Learning: 2026-01-05T23:04:01.518ZApplied to files:
📚 Learning: 2025-10-19T02:44:46.354ZApplied to files:
📚 Learning: 2026-01-05T23:04:01.518ZApplied to files:
📚 Learning: 2025-09-03T01:30:58.001ZApplied to files:
📚 Learning: 2025-09-02T05:33:37.517ZApplied to files:
📚 Learning: 2025-11-06T00:58:23.965ZApplied to files:
📚 Learning: 2025-10-30T03:48:10.513ZApplied to files:
📚 Learning: 2025-10-19T04:55:27.213ZApplied to files:
📚 Learning: 2025-11-08T04:06:33.198ZApplied to files:
📚 Learning: 2026-01-05T23:04:01.518ZApplied to files:
🔇 Additional comments (2)
Comment |
Summary
Fix a memory leak in
RequestContext.doRenderWithBody()whereStrong.Implmemory was leaked when proxying streaming responses through Bun's HTTP server.Problem
When a streaming response (e.g., from a proxied fetch request) was forwarded through Bun's server:
response_body_readable_stream_refwas initialized at line 1836 (fromlock.readable) or line 1841 (viaStrong.init()).Bytesstreams withhas_received_last_chunk=false, a new Strong reference was created at line 1902Strong.Implmemory to leakThis leak accumulated over time with every streaming response proxied through the server.
Solution
Add
this.response_body_readable_stream_ref.deinit()before creating the new Strong reference. This is safe because:streamexists as a stack-local variablestreamwon't be collected betweendeinit()andStrong.init()Test
Added
test/js/web/fetch/server-response-stream-leak.test.tswhich:Related
Similar to the Strong reference leak fixes in: