ruby-concurrency/concurrent-ruby · error · ArgumentError
wrong number of arguments (#{argc} for #{arity}..*)
Error message
wrong number of arguments (#{argc} for #{arity}..*) What it means
Same pre-dispatch check in Concurrent::Async.validate_argc, but for methods with variable arity (defined with *args or optional parameters, so Method#arity is negative). For such methods the library only enforces a minimum of (arity + 1).abs required arguments. This error fires when fewer than that minimum are passed; passing extra arguments is fine.
Source
Thrown at lib/concurrent-ruby/concurrent/async.rb:257
# @note This check is imperfect because of the way Ruby reports the arity of
# methods with a variable number of arguments. It is possible to determine
# if too few arguments are given but impossible to determine if too many
# arguments are given. This check may also fail to recognize dynamic behavior
# of the object, such as methods simulated with `method_missing`.
#
# @see http://www.ruby-doc.org/core-2.1.1/Method.html#method-i-arity Method#arity
# @see http://ruby-doc.org/core-2.1.0/Object.html#method-i-respond_to-3F Object#respond_to?
# @see http://www.ruby-doc.org/core-2.1.0/BasicObject.html#method-i-method_missing BasicObject#method_missing
#
# @!visibility private
def self.validate_argc(obj, method, *args)
argc = args.length
arity = obj.method(method).arity
if arity >= 0 && argc != arity
raise ArgumentError.new("wrong number of arguments (#{argc} for #{arity})")
elsif arity < 0 && (arity = (arity + 1).abs) > argc
raise ArgumentError.new("wrong number of arguments (#{argc} for #{arity}..*)")
end
end
# @!visibility private
def self.included(base)
base.singleton_class.send(:alias_method, :original_new, :new)
base.extend(ClassMethods)
super(base)
end
# @!visibility private
module ClassMethods
def new(*args, &block)
obj = original_new(*args, &block)
obj.send(:init_synchronization)
obj
end
ruby2_keywords :new if respond_to?(:ruby2_keywords, true)View on GitHub (pinned to 0b88d5ff75)
Solutions
- Pass at least `(method.arity + 1).abs` arguments — the required leading parameters of the method.
- When building args dynamically, check `obj.method(:m).arity`; if negative, require `(a + 1).abs` args before calling `proxy.async.m(*args)`.
- Give leading parameters defaults when they are truly optional, so the enforced minimum matches your intent.
- Rescue ArgumentError at the call site; the check is synchronous before scheduling.
Example fix
// before (def connect(host, *options))
proxy.async.connect
// after
proxy.async.connect('db.example.com', timeout: 5) Defensive patterns
Strategy: validation
Validate before calling
m = api.method(:connect)
min_args = m.arity < 0 ? (m.arity + 1).abs : m.arity
raise ArgumentError, "connect needs >= #{min_args} args" if args.size < min_args
proxy.async.connect(*args) Type guard
def meets_minimum_arity?(obj, meth, *args) a = obj.method(meth).arity min = a < 0 ? (a + 1).abs : a args.size >= min end
Try / catch
begin
proxy.async.connect(*args)
rescue ArgumentError => e
raise unless e.message.include?('..*)')
logger.error("too few args for variadic method: #{e.message}")
end Prevention
- For methods with *args or optional params, compute the required minimum as (arity + 1).abs before forwarding dynamic args.
- Prefer arity >= 0 signatures (explicit params) on objects exposed through Concurrent::Async so mismatches are exact.
- Wrap dynamic dispatch sites in a helper that enforces arity once.
When it happens
Trigger: `def connect(host, *options)` (arity -2) called as `proxy.async.connect`; `def run(a, b = 1)` called as `proxy.await.run`; splatting an empty array `proxy.async.setup(*[])` into a method whose leading parameter is required.
Common situations: Optional-parameter methods where callers wrongly assume every parameter is optional; dynamically built argument arrays that do not enforce the required leading parameters; wrapper methods that forward *args into methods needing at least one argument.
Related errors
- wrong number of arguments (#{argc} for #{arity})
- unbuffered channels cannot have a capacity
- capacity must be at least 1 for this buffer type
- no block given
- size must be greater than 0
AI-assisted analysis of ruby-concurrency/concurrent-ruby@0b88d5ff75 (2026-08-21).
Data as JSON: /api/errors/0112ec323665595e.
Report an issue: GitHub.