ruby/ruby · error · RuntimeError

Cannot set ractor local storage for non-current ractor

Error message

Cannot set ractor local storage for non-current ractor

What it means

Obsolete instance-level Ractor#[]= writes ractor-local storage and carries the same restriction as []: only the current ractor may touch its own storage. other_ractor[:key] = value raises RuntimeError 'Cannot set ractor local storage for non-current ractor' before the primitive runs. Use the class form Ractor[:key] = value, or set storage inside the owning ractor's own code.

Source

Thrown at ractor.rb:487

        rb_ractor_make_shareable(obj);
      }
    end
  end

  # Gets a value from ractor-local storage for the current Ractor.
  # Obsolete, use Ractor.[] instead.
  def [](sym)
    if (self != Ractor.current)
      raise RuntimeError, "Cannot get ractor local storage for non-current ractor"
    end
    Primitive.ractor_local_value(sym)
  end

  # Sets a value in ractor-local storage for the current Ractor.
  # Obsolete, use Ractor.[]= instead.
  def []=(sym, val)
    if (self != Ractor.current)
      raise RuntimeError, "Cannot set ractor local storage for non-current ractor"
    end
    Primitive.ractor_local_value_set(sym, val)
  end

  # Gets a value from ractor-local storage for the current Ractor.
  def self.[](sym)
    Primitive.ractor_local_value(sym)
  end

  # Sets a value in ractor-local storage for the current Ractor.
  def self.[]=(sym, val)
    Primitive.ractor_local_value_set(sym, val)
  end

  # call-seq:
  #   Ractor.store_if_absent(key){ init_block }
  #
  # If the corresponding ractor-local value is not set, yields a value with

View on GitHub (pinned to 0e5b888e1c)

Solutions

  1. Set storage inside the ractor that owns it: Ractor.new { Ractor[:cfg] = load_cfg; ... }
  2. Pass initial data as Ractor.new(args) block parameters instead of storage writes from outside
  3. Use the class form Ractor[:key] = value for the current ractor's storage

Example fix

# before
r = Ractor.new { work }
r[:mode] = :fast # RuntimeError: Cannot set ractor local storage for non-current ractor

# after
Ractor[:mode] = :fast # sets MAIN ractor's storage
r = Ractor.new(:fast) { |mode| work(mode) } # child gets data via arguments
Defensive patterns

Strategy: validation

Validate before calling

# set storage only on the current ractor
r[sym] = val if r == Ractor.current
# to initialize a child's storage, set it inside the child's own block:
Ractor.new { Ractor[:mode] = :fast; work }

Type guard

def own_ractor?(r)
  r == Ractor.current
end

Try / catch

begin
  r[sym] = val
rescue RuntimeError => e
  raise unless e.message.include?('ractor local storage')
  Ractor[sym] = val # write the calling ractor's storage instead
end

Prevention

When it happens

Trigger: Parent code trying to 'seed' a spawned ractor via child_ractor[:init] = data before/after spawn; generic obj[key] = assignment helpers that receive a Ractor; Thread#[]= muscle memory applied to Ractor instances.

Common situations: Seeding configuration into workers; code ported from Ruby 3.0 Ractor previews; job frameworks treating ractors as hash-configurable targets.

Related errors


AI-assisted analysis of ruby/ruby@0e5b888e1c (2026-08-21). Data as JSON: /api/errors/29d0d5f187c17adb. Report an issue: GitHub.