{"record":{"id":"7ccc10f4ac4f03fa","repo":"ruby-concurrency/concurrent-ruby","slug":"max-threads-cannot-be-greater-than-default-max-7ccc10","errorCode":null,"errorMessage":"`max_threads` cannot be greater than #{DEFAULT_MAX_POOL_SIZE}","messagePattern":"`max_threads` cannot be greater than #(.+?)","errorType":"exception","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb","lineNumber":157,"sourceCode":"    def prune_pool\n      deprecated \"#prune_pool has no effect and will be removed in next the release, see https://github.com/ruby-concurrency/concurrent-ruby/pull/1082.\"\n    end\n\n    private\n\n    # @!visibility private\n    def ns_initialize(opts)\n      @min_length      = opts.fetch(:min_threads, DEFAULT_MIN_POOL_SIZE).to_i\n      @max_length      = opts.fetch(:max_threads, DEFAULT_MAX_POOL_SIZE).to_i\n      @idletime        = opts.fetch(:idletime, DEFAULT_THREAD_IDLETIMEOUT).to_i\n      @max_queue       = opts.fetch(:max_queue, DEFAULT_MAX_QUEUE_SIZE).to_i\n      @synchronous     = opts.fetch(:synchronous, DEFAULT_SYNCHRONOUS)\n      @fallback_policy = opts.fetch(:fallback_policy, :abort)\n\n      raise ArgumentError.new(\"`synchronous` cannot be set unless `max_queue` is 0\") if @synchronous && @max_queue > 0\n      raise ArgumentError.new(\"#{@fallback_policy} is not a valid fallback policy\") unless FALLBACK_POLICIES.include?(@fallback_policy)\n      raise ArgumentError.new(\"`max_threads` cannot be less than #{DEFAULT_MIN_POOL_SIZE}\") if @max_length < DEFAULT_MIN_POOL_SIZE\n      raise ArgumentError.new(\"`max_threads` cannot be greater than #{DEFAULT_MAX_POOL_SIZE}\") if @max_length > DEFAULT_MAX_POOL_SIZE\n      raise ArgumentError.new(\"`min_threads` cannot be less than #{DEFAULT_MIN_POOL_SIZE}\") if @min_length < DEFAULT_MIN_POOL_SIZE\n      raise ArgumentError.new(\"`min_threads` cannot be more than `max_threads`\") if min_length > max_length\n\n      @pool                 = [] # all workers\n      @ready                = [] # used as a stash (most idle worker is at the start)\n      @queue                = [] # used as queue\n      # @ready or @queue is empty at all times\n      @scheduled_task_count = 0\n      @completed_task_count = 0\n      @largest_length       = 0\n      @workers_counter      = 0\n      @ruby_pid             = $$ # detects if Ruby has forked\n    end\n\n    # @!visibility private\n    def ns_limited_queue?\n      @max_queue != 0\n    end","sourceCodeStart":139,"sourceCodeEnd":175,"githubUrl":"https://github.com/ruby-concurrency/concurrent-ruby/blob/0b88d5ff75f69b3740c8f0868e76f833cb2fd45d/lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#L139-L175","documentation":"On MRI, ThreadPoolExecutor caps max_threads at DEFAULT_MAX_POOL_SIZE = 2_147_483_647 (java.lang.Integer::MAX_VALUE, kept for parity with JRuby). ns_initialize raises ArgumentError when the coerced value exceeds the cap. Values go through to_i, so oversized floats become huge integers and trip this check.","triggerScenarios":"max_threads: 2**31 or above on MRI; max_threads: 5e9 (to_i gives 5000000000); generated config multiplying ENV values into absurd ranges. Note Float::INFINITY.to_i raises FloatDomainError before reaching this check.","commonSituations":"Passing a giant number to mean 'unbounded'; template-generated configs; copying JRuby-capped examples. The identical bug on JRuby reports java_thread_pool_executor.rb instead.","solutions":["Omit max_threads: the default is already 2_147_483_647 (effectively unbounded)","Clamp: max_threads = [wanted, 2_147_483_647].min","For elastic growth prefer Concurrent::CachedThreadPool or Concurrent.global_io_executor"],"exampleFix":"# before\nConcurrent::ThreadPoolExecutor.new(max_threads: 2**32)\n# after\nConcurrent::ThreadPoolExecutor.new(max_threads: 2_147_483_647)","handlingStrategy":"validation","validationCode":"MAX = Concurrent::ThreadPoolExecutor::DEFAULT_MAX_POOL_SIZE\nmax_threads = [Integer(cfg.fetch(:max_threads, MAX)), MAX].min\nConcurrent::ThreadPoolExecutor.new(max_threads: max_threads)","typeGuard":"def valid_thread_count?(v, min = 0, max = 2_147_483_647)\n  v.is_a?(Numeric) && v.to_i.between?(min, max)\nend","tryCatchPattern":"begin\n  Concurrent::ThreadPoolExecutor.new(max_threads: n)\nrescue ArgumentError => e\n  raise unless e.message.start_with?('`max_threads` cannot be greater than')\n  Concurrent::ThreadPoolExecutor.new # default is already the cap\nend","preventionTips":["Omit max_threads for 'unbounded' semantics instead of huge literals","Do not use Float::INFINITY for counts (FloatDomainError)","Cap generated values: [wanted, 2_147_483_647].min; same fix applies on JRuby"],"tags":["ruby","concurrency","thread-pool","argument-error","configuration","integer-overflow"],"backgroundTag":"invalid-thread-pool-configuration","analyzedSha":"0b88d5ff75f69b3740c8f0868e76f833cb2fd45d","analyzedAt":"2026-08-21T20:12:56.291Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}