From: "ioquatix (Samuel Williams) via ruby-core" Date: 2025-05-22T23:44:04+00:00 Subject: [ruby-core:122243] [Ruby Feature#21359] Introduce `Exception#cause=` for Post-Initialization Assignment Issue #21359 has been updated by ioquatix (Samuel Williams). > Serializing exceptions properly without Marshal is probably quite hard yes, not only about the cause but also the internal backtrace representation, the backtrace_locations objects, other internal state for core exceptions that can't always be set in constructor, etc. But is there a need for that? Yes, serialisation with msgpack is painful and impossible to do correctly in some situations, if you have custom serialisation rules for certain object types (using a msgpack factory), you can't use `Marshal.dump` as part of msgpack's serialisation because it won't correctly serialise the internal objects of the exception. ---------------------------------------- Feature #21359: Introduce `Exception#cause=` for Post-Initialization Assignment https://bugs.ruby-lang.org/issues/21359#change-113389 * Author: ioquatix (Samuel Williams) * Status: Open * Assignee: ioquatix (Samuel Williams) ---------------------------------------- Ruby currently allows an exception���s `cause` to be explicitly set **only at the time of raising** using `raise ..., cause: ...`. However, there are valid use cases where it would be convenient to set the cause when creating an exception. ## The Problem Ruby supports exception chaining via the `cause:` keyword during a `raise`, like so: ```ruby raise StandardError.new("failure"), cause: original_exception ``` ## Proposed Solution Introduce `Exception#cause=` as a public setter method on `Exception`, allowing post-initialization assignment of the cause: ```ruby cause = RuntimeError.new("low-level error") error = StandardError.new("higher-level error") error.cause = cause ``` It would be semantically equivalent to the following implementation: ```ruby error = StandardError.new("error") cause = RuntimeError.new("cause") class Exception def cause= value backtrace = self.backtrace_locations raise self, cause: value rescue Exception self.set_backtrace(backtrace) end end p error.cause # nil error.cause = cause p error.cause # => # ``` ### Benefits * Simplifies creation of rich exception objects in frameworks, tools, and tests. * Enables structured error chaining in asynchronous and deferred execution environments. * Avoids misuse of `raise`/`rescue` for control flow and metadata setting. -- https://bugs.ruby-lang.org/ ______________________________________________ ruby-core mailing list -- ruby-core@ml.ruby-lang.org To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org ruby-core info -- https://ml.ruby-lang.org/mailman3/lists/ruby-core.ml.ruby-lang.org/