ruby-concurrency/concurrent-ruby · error · ArgumentError
:class option is ignored when calling on context class, use
Error message
:class option is ignored when calling on context class, use Actor.spawn instead
What it means
In the Edge Actor framework, every Concurrent::Actor::Context subclass gets a class-level `spawn` that always instantiates that same class: `to_spawn_options` merges `class: self` into the options. If the first argument is a Hash containing a `:class` key whose value differs from the context class you called `spawn` on, the library raises ArgumentError rather than silently ignoring your option. Passing `class: MyContext` (the same class) or omitting `:class` is fine. To spawn a different class, call Concurrent::Actor.spawn / spawn! directly with the `:class` option.
Source
Thrown at lib/concurrent-ruby-edge/concurrent/actor/context.rb:135
def self.spawn(name_or_opts, *args, &block)
Actor.spawn to_spawn_options(name_or_opts, *args), &block
end
# behaves as {Concurrent::Actor.spawn!} but :class is auto-inserted based on receiver so it can be omitted.
def self.spawn!(name_or_opts, *args, &block)
Actor.spawn! to_spawn_options(name_or_opts, *args), &block
end
private
def initialize_core(core)
@core = Type! core, Core
end
def self.to_spawn_options(name_or_opts, *args)
if name_or_opts.is_a? ::Hash
if name_or_opts.key?(:class) && name_or_opts[:class] != self
raise ArgumentError,
':class option is ignored when calling on context class, use Actor.spawn instead'
end
name_or_opts.merge class: self
else
{ class: self, name: name_or_opts, args: args }
end
end
# to avoid confusion with Kernel.spawn
undef_method :spawn
end
# Basic Context of an Actor. It supports only linking and it simply terminates on error.
# Uses {Behaviour.basic_behaviour_definition}:
#
# @abstract implement {AbstractContext#on_message}
class Context < AbstractContext
def behaviour_definitionView on GitHub (pinned to 0b88d5ff75)
Solutions
- Drop the `:class` key when spawning on the context class itself: `MyContext.spawn(name: 'worker')`.
- If a different actor class is intended, call `Concurrent::Actor.spawn(class: OtherContext, name: 'worker')` (options-hash form) instead of spawning via the context class.
- Sanitize the options hash before calling: `opts = opts.dup; opts.delete(:class)`.
- Keep `class: MyContext` if you must preserve the key — a value matching the receiver is accepted.
Example fix
// before actor = MyContext.spawn(class: OtherContext, name: 'worker') // after actor = Concurrent::Actor.spawn(class: OtherContext, name: 'worker') // or, when spawning MyContext itself: actor = MyContext.spawn(name: 'worker')
Defensive patterns
Strategy: validation
Validate before calling
def spawn_context(klass, opts)
if opts.is_a?(Hash) && opts.key?(:class) && opts[:class] != klass
raise ArgumentError, "#{klass} cannot spawn with class: #{opts[:class]}; use Concurrent::Actor.spawn"
end
klass.spawn(opts)
end Try / catch
begin
MyContext.spawn(opts)
rescue ArgumentError => e
raise unless e.message.include?(':class option is ignored')
Concurrent::Actor.spawn(opts) # opts keeps its :class
end Prevention
- Build spawn options without a :class key when spawning via a Context subclass.
- Reserve the :class option for Concurrent::Actor.spawn / spawn!.
- Route all spawns through one helper that enforces the option policy.
When it happens
Trigger: Calling `MyContext.spawn(class: OtherContext, name: 'x')` — hash-form first argument with a `:class` key not equal to `MyContext`. Also `MyContext.spawn({class: OtherContext, args: [1]})`. NOT triggered by `MyContext.spawn('name')` (string form builds `{class: self, name: ...}`) or by `MyContext.spawn(class: MyContext, ...)` (equal class is allowed).
Common situations: Copy-pasting a generic `Actor.spawn(class: ..., name: ...)` call onto a Context subclass; a shared spawn helper that builds one options hash for both entry points; refactors where the receiver class changed but the stale `:class` option stayed in the hash.
Related errors
- bad options #{options}
- unrecognized error mode
- Value (#{value.class}) '#{value}' #{message} any of: #{types
- environment has to be a class inheriting from Environment or
- only one of block or value can be supplied
AI-assisted analysis of ruby-concurrency/concurrent-ruby@0b88d5ff75 (2026-08-21).
Data as JSON: /api/errors/c74b12479d5999cd.
Report an issue: GitHub.