{"record":{"id":"0112ec323665595e","repo":"ruby-concurrency/concurrent-ruby","slug":"wrong-number-of-arguments-argc-for-arity-0112ec","errorCode":null,"errorMessage":"wrong number of arguments (#{argc} for #{arity}..*)","messagePattern":"wrong number of arguments \\(#(.+?) for #(.+?)\\.\\.\\*\\)","errorType":"exception","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"lib/concurrent-ruby/concurrent/async.rb","lineNumber":257,"sourceCode":"    # @note This check is imperfect because of the way Ruby reports the arity of\n    #   methods with a variable number of arguments. It is possible to determine\n    #   if too few arguments are given but impossible to determine if too many\n    #   arguments are given. This check may also fail to recognize dynamic behavior\n    #   of the object, such as methods simulated with `method_missing`.\n    #\n    # @see http://www.ruby-doc.org/core-2.1.1/Method.html#method-i-arity Method#arity\n    # @see http://ruby-doc.org/core-2.1.0/Object.html#method-i-respond_to-3F Object#respond_to?\n    # @see http://www.ruby-doc.org/core-2.1.0/BasicObject.html#method-i-method_missing BasicObject#method_missing\n    #\n    # @!visibility private\n    def self.validate_argc(obj, method, *args)\n      argc = args.length\n      arity = obj.method(method).arity\n\n      if arity >= 0 && argc != arity\n        raise ArgumentError.new(\"wrong number of arguments (#{argc} for #{arity})\")\n      elsif arity < 0 && (arity = (arity + 1).abs) > argc\n        raise ArgumentError.new(\"wrong number of arguments (#{argc} for #{arity}..*)\")\n      end\n    end\n\n    # @!visibility private\n    def self.included(base)\n      base.singleton_class.send(:alias_method, :original_new, :new)\n      base.extend(ClassMethods)\n      super(base)\n    end\n\n    # @!visibility private\n    module ClassMethods\n      def new(*args, &block)\n        obj = original_new(*args, &block)\n        obj.send(:init_synchronization)\n        obj\n      end\n      ruby2_keywords :new if respond_to?(:ruby2_keywords, true)","sourceCodeStart":239,"sourceCodeEnd":275,"githubUrl":"https://github.com/ruby-concurrency/concurrent-ruby/blob/0b88d5ff75f69b3740c8f0868e76f833cb2fd45d/lib/concurrent-ruby/concurrent/async.rb#L239-L275","documentation":"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.","triggerScenarios":"`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.","commonSituations":"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.","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."],"exampleFix":"// before (def connect(host, *options))\nproxy.async.connect\n\n// after\nproxy.async.connect('db.example.com', timeout: 5)","handlingStrategy":"validation","validationCode":"m = api.method(:connect)\nmin_args = m.arity < 0 ? (m.arity + 1).abs : m.arity\nraise ArgumentError, \"connect needs >= #{min_args} args\" if args.size < min_args\nproxy.async.connect(*args)","typeGuard":"def meets_minimum_arity?(obj, meth, *args)\n  a = obj.method(meth).arity\n  min = a < 0 ? (a + 1).abs : a\n  args.size >= min\nend","tryCatchPattern":"begin\n  proxy.async.connect(*args)\nrescue ArgumentError => e\n  raise unless e.message.include?('..*)')\n  logger.error(\"too few args for variadic method: #{e.message}\")\nend","preventionTips":["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."],"tags":["concurrent-ruby","async","arity","varargs","argumenterror"],"backgroundTag":"wrong-number-of-arguments","analyzedSha":"0b88d5ff75f69b3740c8f0868e76f833cb2fd45d","analyzedAt":"2026-08-21T20:12:56.291Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}