[ruby-core:125728] [Ruby Bug#22109] Unexpected or misleading error when subclass of a ractor calls a new method on itself
Issue #22109 has been reported by miles-georgi (Miles Georgi). ---------------------------------------- Bug #22109: Unexpected or misleading error when subclass of a ractor calls a new method on itself https://bugs.ruby-lang.org/issues/22109 * Author: miles-georgi (Miles Georgi) * Status: Open * ruby -v: ruby 4.0.5 (2026-05-20 revision 64336ffd0e) +PRISM [x86_64-linux] * Backport: 3.3: UNKNOWN, 3.4: UNKNOWN, 4.0: UNKNOWN ---------------------------------------- Hey hey! When I run the following code: ```ruby class SubRactor < Ractor attr_accessor :foo end SubRactor.new { puts foo }.join ``` I get the following error: ``` can not access instance variables of shareable objects from non-main Ractors (Ractor::IsolationError) ``` Unclear if I shouldn't get an error of any sort in this situation, but if this is a legitimate error situation, this error seems inaccurate since Ractors can obviously access instance variables of shareable objects. A tiny script that shows that: ```ruby class C attr_accessor :foo def initialize = self.foo = 100 INSTANCE = new.freeze end raise "not shareable!" unless Ractor.shareable?(C::INSTANCE) Ractor.new { puts C::INSTANCE.foo }.join ``` This prints out 100 as expected instead of giving that error. This happens on both: ruby 4.1.0dev (2026-06-11T14:25:18Z master 8e8682fc23) +PRISM [x86_64-linux] and ruby 4.0.5 (2026-05-20 revision 64336ffd0e) +PRISM [x86_64-linux] The script is so puny seems I shouldn't upload the file but let me know if I should just always upload a script file when filing these even when they are trivially small. Cheers! -- https://bugs.ruby-lang.org/
Issue #22109 has been updated by jhawthorn (John Hawthorn). I don't think this has anything to do with the method or the subclass. The message could probably be improved, but the warning exists because instance variables on classes like `Ractor` (or other objects which are shareable without being frozen) are only accessible by the main Ractor. ``` ❮ ruby -ve 'Ractor.new{ @foo = 123 }.join' ruby 4.0.5 (2026-05-20 revision 64336ffd0e) +PRISM [arm64-darwin25] -e:1: warning: Ractor API is experimental and may change in future versions of Ruby. #<Thread:0x0000000120db72b8 run> terminated with exception (report_on_exception is true): -e:1:in 'block in <main>': can not access instance variables of shareable objects from non-main Ractors (Ractor::IsolationError) -e:1:in 'Ractor#join': thrown by remote Ractor. (Ractor::RemoteError) from -e:1:in '<main>' -e:1:in 'block in <main>': can not access instance variables of shareable objects from non-main Ractors (Ractor::IsolationError) ``` ---------------------------------------- Bug #22109: Unexpected or misleading error when subclass of a ractor calls a new method on itself https://bugs.ruby-lang.org/issues/22109#change-117613 * Author: miles-georgi (Miles Georgi) * Status: Open * ruby -v: ruby 4.0.5 (2026-05-20 revision 64336ffd0e) +PRISM [x86_64-linux] * Backport: 3.3: UNKNOWN, 3.4: UNKNOWN, 4.0: UNKNOWN ---------------------------------------- Hey hey! When I run the following code: ```ruby class SubRactor < Ractor attr_accessor :foo end SubRactor.new { puts foo }.join ``` I get the following error: ``` can not access instance variables of shareable objects from non-main Ractors (Ractor::IsolationError) ``` Unclear if I shouldn't get an error of any sort in this situation, but if this is a legitimate error situation, this error seems inaccurate since Ractors can obviously access instance variables of shareable objects. A tiny script that shows that: ```ruby class C attr_accessor :foo def initialize = self.foo = 100 INSTANCE = new.freeze end raise "not shareable!" unless Ractor.shareable?(C::INSTANCE) Ractor.new { puts C::INSTANCE.foo }.join ``` This prints out 100 as expected instead of giving that error. This happens on both: ruby 4.1.0dev (2026-06-11T14:25:18Z master 8e8682fc23) +PRISM [x86_64-linux] and ruby 4.0.5 (2026-05-20 revision 64336ffd0e) +PRISM [x86_64-linux] The script is so puny seems I shouldn't upload the file but let me know if I should just always upload a script file when filing these even when they are trivially small. Cheers! -- https://bugs.ruby-lang.org/
Issue #22109 has been updated by miles-georgi (Miles Georgi). Oh good catch that subclassing is irrelevant! Same happens with the simpler `Ractor.new { @foo }.join` which is a read operation instead of write. However...
instance variables on classes like `Ractor` (or other objects which are shareable without being frozen) are only accessible by the main Ractor.
this doesn't appear to be true: ```ruby class C singleton_class.attr_accessor :foo end C.foo = 100 Ractor.new { puts C.foo }.join ``` This prints out `100` instead of giving an error. The error message itself just doesn't seem to be true. Ractors can access instance variables of shareable objects, classes or otherwise. It seems like if this is a legit error the message should be something like "(non-main)? Ractors cannot access their own instance variables." I'm not sure what class the error should be since, unless I'm confused, it doesn't seem like an "isolation" issue for a ractor to access its own instance variables. ---------------------------------------- Bug #22109: Unexpected or misleading error when subclass of a ractor calls a new method on itself https://bugs.ruby-lang.org/issues/22109#change-117617 * Author: miles-georgi (Miles Georgi) * Status: Open * ruby -v: ruby 4.0.5 (2026-05-20 revision 64336ffd0e) +PRISM [x86_64-linux] * Backport: 3.3: UNKNOWN, 3.4: UNKNOWN, 4.0: UNKNOWN ---------------------------------------- Hey hey! When I run the following code: ```ruby class SubRactor < Ractor attr_accessor :foo end SubRactor.new { puts foo }.join ``` I get the following error: ``` can not access instance variables of shareable objects from non-main Ractors (Ractor::IsolationError) ``` Unclear if I shouldn't get an error of any sort in this situation, but if this is a legitimate error situation, this error seems inaccurate since Ractors can obviously access instance variables of shareable objects. A tiny script that shows that: ```ruby class C attr_accessor :foo def initialize = self.foo = 100 INSTANCE = new.freeze end raise "not shareable!" unless Ractor.shareable?(C::INSTANCE) Ractor.new { puts C::INSTANCE.foo }.join ``` This prints out 100 as expected instead of giving that error. This happens on both: ruby 4.1.0dev (2026-06-11T14:25:18Z master 8e8682fc23) +PRISM [x86_64-linux] and ruby 4.0.5 (2026-05-20 revision 64336ffd0e) +PRISM [x86_64-linux] The script is so puny seems I shouldn't upload the file but let me know if I should just always upload a script file when filing these even when they are trivially small. Cheers! -- https://bugs.ruby-lang.org/
Issue #22109 has been updated by byroot (Jean Boussier).
Ractors can access instance variables of shareable objects, classes or otherwise.
Only if the object the variable points at is itself shareable. ```ruby class C singleton_class.attr_accessor :foo end C.foo = Object.new Ractor.new { puts C.foo }.join ``` It is however true we could treat `Ractor` instances more like classes and allow instance variable access with the same restriction, but it means we need to use RCU when adding or removing instance variables on them, like RClass does. It's definitely doable, I don't know if it's desirable though. ---------------------------------------- Bug #22109: Unexpected or misleading error when subclass of a ractor calls a new method on itself https://bugs.ruby-lang.org/issues/22109#change-117620 * Author: miles-georgi (Miles Georgi) * Status: Open * ruby -v: ruby 4.0.5 (2026-05-20 revision 64336ffd0e) +PRISM [x86_64-linux] * Backport: 3.3: UNKNOWN, 3.4: UNKNOWN, 4.0: UNKNOWN ---------------------------------------- Hey hey! When I run the following code: ```ruby class SubRactor < Ractor attr_accessor :foo end SubRactor.new { puts foo }.join ``` I get the following error: ``` can not access instance variables of shareable objects from non-main Ractors (Ractor::IsolationError) ``` Unclear if I shouldn't get an error of any sort in this situation, but if this is a legitimate error situation, this error seems inaccurate since Ractors can obviously access instance variables of shareable objects. A tiny script that shows that: ```ruby class C attr_accessor :foo def initialize = self.foo = 100 INSTANCE = new.freeze end raise "not shareable!" unless Ractor.shareable?(C::INSTANCE) Ractor.new { puts C::INSTANCE.foo }.join ``` This prints out 100 as expected instead of giving that error. This happens on both: ruby 4.1.0dev (2026-06-11T14:25:18Z master 8e8682fc23) +PRISM [x86_64-linux] and ruby 4.0.5 (2026-05-20 revision 64336ffd0e) +PRISM [x86_64-linux] The script is so puny seems I shouldn't upload the file but let me know if I should just always upload a script file when filing these even when they are trivially small. Cheers! -- https://bugs.ruby-lang.org/
Issue #22109 has been updated by miles-georgi (Miles Georgi). byroot (Jean Boussier) wrote in #note-3:
Ractors can access instance variables of shareable objects, classes or otherwise.
Only if the object the variable points at is itself shareable.
Ah, right, true!
It is however true we could treat `Ractor` instances more like classes and allow instance variable access with the same restriction, but it means we need to use RCU when adding or removing instance variables on them, like RClass does.
It's definitely doable, I don't know if it's desirable though. Well, to be clear, the thing that surprised me was not that instances of Ractor couldn't access the instance variables of other instances of Ractor. That makes total sense to me. It was that instances of Ractor are not be able to use instance variables at all, ie, their own instance variables (with the exception of the main Ractor, which can, but I'm going to ignore the main Ractor from here-on-out.)
It doesn't seem desirable to me to let instances of Ractor access each other's instance variables but it does seem like it would be desirable to let instances of Ractor access their own instance variables. But if it's not feasible to do that or not desirable, I guess I would then suggest that instances of Ractor should be frozen. I think that would result in a less confusing error message and communicate the restriction better. Regarding desirability of allowing ractors to make use of instance variables, I could explain what I was up to that led me to attempt that in the first place. Most of the Ractors I've been experimenting with have a similar structure: the block passed to new has some setup with some local variables to hold state and then a loop with a case statement that does different things in different when/in clauses depending on the message received. One of these case statements was getting pretty gigantic so I wanted to organize the logic better. The first thing that made sense to me to try was to move logic out of the when clauses into private helper methods. This though naturally made me move state from local variables in the closure to instance variables. There are other ways I could manage the complexity, so it's not like I can't live without instance variables, but it was natural to try and the misleading error message inspired me to file this issue. But yeah, regardless of the workarounds, it seems natural to me to be able to attempt what I attempted and in other languages I've implemented actors that use instance variables since closures weren't even an option. So it was just surprising to me. So to recap, I suppose my suggestion (though I don't know the limitations, etc, so could be a bad suggestion) would be to either allow instances of Ractor to use their own instance variables or freeze instances of Ractor so that when somebody attempts to assign an instance variable in a ractor they get an error message that results in "oohhhh OK" instead of "huh? that's not true." If that's not doable or desirable then I'd recommend changing the error message to reflect the actual limitation which is that non-main ractors cannot make use of instance variables. ---------------------------------------- Bug #22109: Unexpected or misleading error when subclass of a ractor calls a new method on itself https://bugs.ruby-lang.org/issues/22109#change-117627 * Author: miles-georgi (Miles Georgi) * Status: Open * ruby -v: ruby 4.0.5 (2026-05-20 revision 64336ffd0e) +PRISM [x86_64-linux] * Backport: 3.3: UNKNOWN, 3.4: UNKNOWN, 4.0: UNKNOWN ---------------------------------------- Hey hey! When I run the following code: ```ruby class SubRactor < Ractor attr_accessor :foo end SubRactor.new { puts foo }.join ``` I get the following error: ``` can not access instance variables of shareable objects from non-main Ractors (Ractor::IsolationError) ``` Unclear if I shouldn't get an error of any sort in this situation, but if this is a legitimate error situation, this error seems inaccurate since Ractors can obviously access instance variables of shareable objects. A tiny script that shows that: ```ruby class C attr_accessor :foo def initialize = self.foo = 100 INSTANCE = new.freeze end raise "not shareable!" unless Ractor.shareable?(C::INSTANCE) Ractor.new { puts C::INSTANCE.foo }.join ``` This prints out 100 as expected instead of giving that error. This happens on both: ruby 4.1.0dev (2026-06-11T14:25:18Z master 8e8682fc23) +PRISM [x86_64-linux] and ruby 4.0.5 (2026-05-20 revision 64336ffd0e) +PRISM [x86_64-linux] The script is so puny seems I shouldn't upload the file but let me know if I should just always upload a script file when filing these even when they are trivially small. Cheers! -- https://bugs.ruby-lang.org/
Issue #22109 has been updated by miles-georgi (Miles Georgi). Somebody mentioned to me some potentially annoying aspects of freezing ractor instances like not being able to extend them with convenience methods. So freezing seems like a pretty bad suggestion in retrospect. So I suspect improving the existing error message when this situation arises might be the path we're on, unless it's feasible and desirable to let ractor instances manage their own instance variables. ---------------------------------------- Bug #22109: Unexpected or misleading error when subclass of a ractor calls a new method on itself https://bugs.ruby-lang.org/issues/22109#change-117630 * Author: miles-georgi (Miles Georgi) * Status: Open * ruby -v: ruby 4.0.5 (2026-05-20 revision 64336ffd0e) +PRISM [x86_64-linux] * Backport: 3.3: UNKNOWN, 3.4: UNKNOWN, 4.0: UNKNOWN ---------------------------------------- Hey hey! When I run the following code: ```ruby class SubRactor < Ractor attr_accessor :foo end SubRactor.new { puts foo }.join ``` I get the following error: ``` can not access instance variables of shareable objects from non-main Ractors (Ractor::IsolationError) ``` Unclear if I shouldn't get an error of any sort in this situation, but if this is a legitimate error situation, this error seems inaccurate since Ractors can obviously access instance variables of shareable objects. A tiny script that shows that: ```ruby class C attr_accessor :foo def initialize = self.foo = 100 INSTANCE = new.freeze end raise "not shareable!" unless Ractor.shareable?(C::INSTANCE) Ractor.new { puts C::INSTANCE.foo }.join ``` This prints out 100 as expected instead of giving that error. This happens on both: ruby 4.1.0dev (2026-06-11T14:25:18Z master 8e8682fc23) +PRISM [x86_64-linux] and ruby 4.0.5 (2026-05-20 revision 64336ffd0e) +PRISM [x86_64-linux] The script is so puny seems I shouldn't upload the file but let me know if I should just always upload a script file when filing these even when they are trivially small. Cheers! -- https://bugs.ruby-lang.org/
participants (3)
-
byroot (Jean Boussier) -
jhawthorn (John Hawthorn) -
miles-georgi (Miles Georgi)