Bug #22109
openUnexpected or misleading error when subclass of a ractor calls a new method on itself
Description
Hey hey!
When I run the following code:
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:
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!
Updated by jhawthorn (John Hawthorn) 2 days ago
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)
Updated by miles-georgi (Miles Georgi) 2 days ago
· Edited
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:
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 an accurate message should be something like "non-main Ractors cannot access their own instance variables, nor those of any other Ractor"
I'm not sure what class the error should be in case of a non-main Ractor attempting to access its own instance variables since, unless I'm confused, it doesn't seem like an "isolation" issue for a ractor to access its own instance variables.
Updated by byroot (Jean Boussier) 1 day ago
Ractors can access instance variables of shareable objects, classes or otherwise.
Only if the object the variable points at is itself shareable.
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.
Updated by miles-georgi (Miles Georgi) 1 day ago
· Edited
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
Ractorinstances 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.
So to recap, I suppose my 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.
Updated by miles-georgi (Miles Georgi) 1 day ago
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.