Bug #21716
openYJIT panic: "all PendingBranchRefs should be unique" in net/http response reading (infinite unwind loop)
Description
We encountered a YJIT panic in production that caused the process to enter an infinite logging loop for several hours. The panic occurs within yjit/src/core.rs when handling branch references.
The trigger appears to be in net/http, specifically when reading a response body (possibly involving chunked encoding or zlib) inside a Datadog trace transport flush.
Key Observations:
The Panic: YJIT fails with all PendingBranchRefs should be unique when ready to construct a Block.
The Loop: After the panic, the process fails to exit and instead logs rust_begin_unwind and try_fold iterator errors repeatedly, filling logs for hours.
System Configuration
Ruby Version: ruby 3.4.7 (2025-10-08 revision 7a5688e2a2) +YJIT +PRISM [aarch64-linux]
Environment: Linux aarch64 (AWS Graviton/ARM)
Reproduction Context
While we cannot provide a standalone reproduction script yet, the crash happens intermittently during a Net::HTTP request initiated by datadog-ruby (v2.17.0) to flush traces to a Unix socket, which is wrapped by sentry-ruby (v5.26.0).
Ruby Location: /gems/net-http-0.6.0/lib/net/http/response.rb:604
Rust Location: ./yjit/src/core.rs:2403:27
Backtrace & Logs
ruby: YJIT has panicked. More info to follow...
thread '<unnamed>' panicked at 'all PendingBranchRefs should be unique when ready to construct a Block', ./yjit/src/core.rs:2403:27
stack backtrace:
0: rust_begin_unwind
at /rustc/.../library/std/src/panicking.rs:578:5
...
28: yjit::core::branch_stub_hit
at /workspace/ruby-3.4.7/yjit/src/core.rs:3492:9
/gems/net-http-0.6.0/lib/net/http/response.rb:604: [BUG] YJIT: panicked at 'all PendingBranchRefs should be unique when ready to construct a Block', ./yjit/src/core.rs:2403:27
-- Control frame information -----------------------------------------------
c:0047 p:0049 s:0248 e:000247 BLOCK /gems/net-http-0.6.0/lib/net/http/response.rb:604
c:0046 p:0098 s:0243 e:000242 METHOD /gems/net-http-0.6.0/lib/net/http/response.rb:588
c:0045 p:0004 s:0235 e:000234 METHOD /gems/net-http-0.6.0/lib/net/http/response.rb:593
...
c:0039 p:0033 s:0196 e:000195 BLOCK /gems/sentry-ruby-5.26.0/lib/sentry/net/http.rb:44
...
c:0033 p:0023 s:0158 e:000157 METHOD /gems/datadog-2.17.0/lib/datadog/core/transport/http/adapters/unix_socket.rb:43
c:0032 p:0066 s:0152 e:000151 METHOD /gems/datadog-2.17.0/lib/datadog/core/transport/http/adapters/net.rb:77
The stack suggests the crash happens during branch_stub_hit resolution. The presence of sentry-ruby and datadog suggests complex interaction with Net::HTTP patching.
The infinite loop of logs following the crash looks like this (repeated):
/usr/lib/libruby.so.3.4(try_fold<alloc::vec::into_iter::IntoIter<alloc::rc::Rc<yjit::core::PendingBranch> ...
``
This suggests the panic handler itself is tripping over the corrupted `PendingBranch` state. We encountered a YJIT panic in production that caused the process to enter an infinite logging loop for several hours. The panic occurs within `yjit/src/core.rs` when handling branch references.
The trigger appears to be in `net/http`, specifically when reading a response body (possibly involving chunked encoding or zlib) inside a Datadog trace transport flush.