{"record":{"id":"c19eaa1ba1f0ef9e","repo":"ruby-concurrency/concurrent-ruby","slug":"argumenterror","errorCode":null,"errorMessage":"ArgumentError","messagePattern":"ArgumentError","errorType":"exception","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"lib/concurrent-ruby/concurrent/promises.rb","lineNumber":1016,"sourceCode":"      def value!(timeout = nil, timeout_value = nil)\n        if wait_until_resolved! timeout\n          internal_state.value\n        else\n          timeout_value\n        end\n      end\n\n      # Allows rejected Future to be risen with `raise` method.\n      # If the reason is not an exception `Runtime.new(reason)` is returned.\n      #\n      # @example\n      #   raise Promises.rejected_future(StandardError.new(\"boom\"))\n      #   raise Promises.rejected_future(\"or just boom\")\n      # @raise [Concurrent::Error] when raising not rejected future\n      # @return [Exception]\n      def exception(*args)\n        raise Concurrent::Error, 'it is not rejected' unless rejected?\n        raise ArgumentError unless args.size <= 1\n        reason = Array(internal_state.reason).flatten.compact\n        callsites = SET_BACKTRACE_LOCATIONS_SUPPORTED ? caller_locations : caller\n        if reason.size > 1\n          ex = Concurrent::MultipleErrors.new reason\n          ex.set_backtrace(callsites)\n          ex\n        else\n          ex = if reason[0].respond_to? :exception\n                 reason[0].exception(*args)\n               else\n                 RuntimeError.new(reason[0]).exception(*args)\n               end\n          if SET_BACKTRACE_LOCATIONS_SUPPORTED && (locations = ex.backtrace_locations)\n            ex.set_backtrace locations + callsites\n          else\n            ex.set_backtrace Array(ex.backtrace) + callsites.map(&:to_s)\n          end\n          ex","sourceCodeStart":998,"sourceCodeEnd":1034,"githubUrl":"https://github.com/ruby-concurrency/concurrent-ruby/blob/0b88d5ff75f69b3740c8f0868e76f833cb2fd45d/lib/concurrent-ruby/concurrent/promises.rb#L998-L1034","documentation":"Future#exception(*args) follows Exception#exception semantics: at most one optional argument (a message) is allowed. After the rejected? precondition, promises.rb:1016 raises a bare ArgumentError when args.size > 1. Only a rejected future can reach this line, since the state check at :1015 runs first.","triggerScenarios":"future.exception('boom', caller) with two arguments; splatting caller-supplied arguments through: future.exception(*args) where args has 2+ elements.","commonSituations":"Generic exception-building helpers that pass extra context (message + backtrace) into .exception; porting exception-construction patterns from other libraries that accept a backtrace argument.","solutions":["Pass at most one argument: future.exception('boom').","Truncate splats defensively: future.exception(*args.take(1)).","To attach a backtrace, call .set_backtrace on the returned exception instead of passing it as an argument."],"exampleFix":"# before\nex = future.exception('boom', caller) # ArgumentError: 2 args\n\n# after\nex = future.exception('boom')\nex.set_backtrace(caller) if ex","handlingStrategy":"validation","validationCode":"raise ArgumentError, 'at most one argument' if args.size > 1\nfuture.exception(*args.take(1))","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Pass at most one message argument to .exception.","Never splat unbounded arrays into .exception; truncate with take(1).","Attach backtraces via set_backtrace on the returned exception."],"tags":["ruby","concurrency","promises","arity","argumenterror"],"backgroundTag":"arity-error","analyzedSha":"0b88d5ff75f69b3740c8f0868e76f833cb2fd45d","analyzedAt":"2026-08-21T20:12:56.291Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}