[ruby-core:125235] [Ruby Bug#21991] `$!` stays as the first exception in Ruby Box
Issue #21991 has been reported by tikkss (Tsutomu Katsube). ---------------------------------------- Bug #21991: `$!` stays as the first exception in Ruby Box https://bugs.ruby-lang.org/issues/21991 * Author: tikkss (Tsutomu Katsube) * Status: Open * ruby -v: ruby 4.0.2 (2026-03-17 revision d3da9fec82) +PRISM [x86_64-darwin24] * Backport: 3.2: UNKNOWN, 3.3: UNKNOWN, 3.4: UNKNOWN, 4.0: UNKNOWN ---------------------------------------- Description --- When Ruby Box is enabled (`RUBY_BOX=1`), `$!` inside `rescue` does not change after the first exception. `$!` is expected to show the exception for each `rescue` block, but it always shows the first one. Steps to reproduce --- ```ruby # test.rb begin raise "First error" rescue pp $! end begin raise "Second error" rescue pp $! end begin raise "Third error" rescue pp $! end ``` Expected result --- ```console $ RUBY_BOX=1 ruby test.rb ruby: warning: Ruby::Box is experimental, and the behavior may change in the future! See https://docs.ruby-lang.org/en/4.0/Ruby/Box.html for known issues, etc. #<RuntimeError: First error> #<RuntimeError: Second error> #<RuntimeError: Third error> ``` Actual result --- ```console $ RUBY_BOX=1 ruby test.rb ruby: warning: Ruby::Box is experimental, and the behavior may change in the future! See https://docs.ruby-lang.org/en/4.0/Ruby/Box.html for known issues, etc. #<RuntimeError: First error> #<RuntimeError: First error> #<RuntimeError: First error> ``` Additional information --- This issue does not reproduce when `RUBY_BOX=1` is not set: ```console $ ruby test.rb #<RuntimeError: First error> #<RuntimeError: Second error> #<RuntimeError: Third error> ``` Also, this issue does not reproduce when the exception object is captured explicitly in the `rescue` clause: ```ruby # test.rb begin raise "First error" rescue => e pp e end begin raise "Second error" rescue => e pp e end begin raise "Third error" rescue => e pp e end ``` ```console $ RUBY_BOX=1 ruby test.rb ruby: warning: Ruby::Box is experimental, and the behavior may change in the future! See https://docs.ruby-lang.org/en/4.0/Ruby/Box.html for known issues, etc. #<RuntimeError: First error> #<RuntimeError: Second error> #<RuntimeError: Third error> ``` -- https://bugs.ruby-lang.org/
Issue #21991 has been updated by dak2 (Daichi Kamiyama). I created a patch for this issue. https://github.com/ruby/ruby/pull/16863 @tagomoris Could you review this? ---------------------------------------- Bug #21991: `$!` stays as the first exception in Ruby Box https://bugs.ruby-lang.org/issues/21991#change-117211 * Author: tikkss (Tsutomu Katsube) * Status: Open * Assignee: tagomoris (Satoshi Tagomori) * ruby -v: ruby 4.0.2 (2026-03-17 revision d3da9fec82) +PRISM [x86_64-darwin24] * Backport: 3.2: UNKNOWN, 3.3: UNKNOWN, 3.4: UNKNOWN, 4.0: UNKNOWN ---------------------------------------- Description --- When Ruby Box is enabled (`RUBY_BOX=1`), `$!` inside `rescue` does not change after the first exception. `$!` is expected to show the exception for each `rescue` block, but it always shows the first one. Steps to reproduce --- ```ruby # test.rb begin raise "First error" rescue pp $! end begin raise "Second error" rescue pp $! end begin raise "Third error" rescue pp $! end ``` Expected result --- ```console $ RUBY_BOX=1 ruby test.rb ruby: warning: Ruby::Box is experimental, and the behavior may change in the future! See https://docs.ruby-lang.org/en/4.0/Ruby/Box.html for known issues, etc. #<RuntimeError: First error> #<RuntimeError: Second error> #<RuntimeError: Third error> ``` Actual result --- ```console $ RUBY_BOX=1 ruby test.rb ruby: warning: Ruby::Box is experimental, and the behavior may change in the future! See https://docs.ruby-lang.org/en/4.0/Ruby/Box.html for known issues, etc. #<RuntimeError: First error> #<RuntimeError: First error> #<RuntimeError: First error> ``` Additional information --- This issue does not reproduce when `RUBY_BOX=1` is not set: ```console $ ruby test.rb #<RuntimeError: First error> #<RuntimeError: Second error> #<RuntimeError: Third error> ``` Also, this issue does not reproduce when the exception object is captured explicitly in the `rescue` clause: ```ruby # test.rb begin raise "First error" rescue => e pp e end begin raise "Second error" rescue => e pp e end begin raise "Third error" rescue => e pp e end ``` ```console $ RUBY_BOX=1 ruby test.rb ruby: warning: Ruby::Box is experimental, and the behavior may change in the future! See https://docs.ruby-lang.org/en/4.0/Ruby/Box.html for known issues, etc. #<RuntimeError: First error> #<RuntimeError: Second error> #<RuntimeError: Third error> ``` -- https://bugs.ruby-lang.org/
Issue #21991 has been updated by tikkss (Tsutomu Katsube). I have tried to fix this issue at RubyKaigi 2026 on Code Party. However, I was unable to fix it. I have confirmed that this issue has been resolved in 12bb895526. Thanks for your patch! ---------------------------------------- Bug #21991: `$!` stays as the first exception in Ruby Box https://bugs.ruby-lang.org/issues/21991#change-117239 * Author: tikkss (Tsutomu Katsube) * Status: Closed * Assignee: tagomoris (Satoshi Tagomori) * ruby -v: ruby 4.0.2 (2026-03-17 revision d3da9fec82) +PRISM [x86_64-darwin24] * Backport: 3.2: UNKNOWN, 3.3: UNKNOWN, 3.4: UNKNOWN, 4.0: UNKNOWN ---------------------------------------- Description --- When Ruby Box is enabled (`RUBY_BOX=1`), `$!` inside `rescue` does not change after the first exception. `$!` is expected to show the exception for each `rescue` block, but it always shows the first one. Steps to reproduce --- ```ruby # test.rb begin raise "First error" rescue pp $! end begin raise "Second error" rescue pp $! end begin raise "Third error" rescue pp $! end ``` Expected result --- ```console $ RUBY_BOX=1 ruby test.rb ruby: warning: Ruby::Box is experimental, and the behavior may change in the future! See https://docs.ruby-lang.org/en/4.0/Ruby/Box.html for known issues, etc. #<RuntimeError: First error> #<RuntimeError: Second error> #<RuntimeError: Third error> ``` Actual result --- ```console $ RUBY_BOX=1 ruby test.rb ruby: warning: Ruby::Box is experimental, and the behavior may change in the future! See https://docs.ruby-lang.org/en/4.0/Ruby/Box.html for known issues, etc. #<RuntimeError: First error> #<RuntimeError: First error> #<RuntimeError: First error> ``` Additional information --- This issue does not reproduce when `RUBY_BOX=1` is not set: ```console $ ruby test.rb #<RuntimeError: First error> #<RuntimeError: Second error> #<RuntimeError: Third error> ``` Also, this issue does not reproduce when the exception object is captured explicitly in the `rescue` clause: ```ruby # test.rb begin raise "First error" rescue => e pp e end begin raise "Second error" rescue => e pp e end begin raise "Third error" rescue => e pp e end ``` ```console $ RUBY_BOX=1 ruby test.rb ruby: warning: Ruby::Box is experimental, and the behavior may change in the future! See https://docs.ruby-lang.org/en/4.0/Ruby/Box.html for known issues, etc. #<RuntimeError: First error> #<RuntimeError: Second error> #<RuntimeError: Third error> ``` -- https://bugs.ruby-lang.org/
participants (2)
-
dak2 (Daichi Kamiyama) -
tikkss (Tsutomu Katsube)