ruby-concurrency/concurrent-ruby · error · ArgumentError
`max_threads` cannot be greater than #{DEFAULT_MAX_POOL_SIZE
Error message
`max_threads` cannot be greater than #{DEFAULT_MAX_POOL_SIZE} What it means
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.
Source
Thrown at lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb:157
def prune_pool
deprecated "#prune_pool has no effect and will be removed in next the release, see https://github.com/ruby-concurrency/concurrent-ruby/pull/1082."
end
private
# @!visibility private
def ns_initialize(opts)
@min_length = opts.fetch(:min_threads, DEFAULT_MIN_POOL_SIZE).to_i
@max_length = opts.fetch(:max_threads, DEFAULT_MAX_POOL_SIZE).to_i
@idletime = opts.fetch(:idletime, DEFAULT_THREAD_IDLETIMEOUT).to_i
@max_queue = opts.fetch(:max_queue, DEFAULT_MAX_QUEUE_SIZE).to_i
@synchronous = opts.fetch(:synchronous, DEFAULT_SYNCHRONOUS)
@fallback_policy = opts.fetch(:fallback_policy, :abort)
raise ArgumentError.new("`synchronous` cannot be set unless `max_queue` is 0") if @synchronous && @max_queue > 0
raise ArgumentError.new("#{@fallback_policy} is not a valid fallback policy") unless FALLBACK_POLICIES.include?(@fallback_policy)
raise ArgumentError.new("`max_threads` cannot be less than #{DEFAULT_MIN_POOL_SIZE}") if @max_length < DEFAULT_MIN_POOL_SIZE
raise ArgumentError.new("`max_threads` cannot be greater than #{DEFAULT_MAX_POOL_SIZE}") if @max_length > DEFAULT_MAX_POOL_SIZE
raise ArgumentError.new("`min_threads` cannot be less than #{DEFAULT_MIN_POOL_SIZE}") if @min_length < DEFAULT_MIN_POOL_SIZE
raise ArgumentError.new("`min_threads` cannot be more than `max_threads`") if min_length > max_length
@pool = [] # all workers
@ready = [] # used as a stash (most idle worker is at the start)
@queue = [] # used as queue
# @ready or @queue is empty at all times
@scheduled_task_count = 0
@completed_task_count = 0
@largest_length = 0
@workers_counter = 0
@ruby_pid = $$ # detects if Ruby has forked
end
# @!visibility private
def ns_limited_queue?
@max_queue != 0
endView on GitHub (pinned to 0b88d5ff75)
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
Example fix
# before Concurrent::ThreadPoolExecutor.new(max_threads: 2**32) # after Concurrent::ThreadPoolExecutor.new(max_threads: 2_147_483_647)
Defensive patterns
Strategy: validation
Validate before calling
MAX = Concurrent::ThreadPoolExecutor::DEFAULT_MAX_POOL_SIZE max_threads = [Integer(cfg.fetch(:max_threads, MAX)), MAX].min Concurrent::ThreadPoolExecutor.new(max_threads: max_threads)
Type guard
def valid_thread_count?(v, min = 0, max = 2_147_483_647) v.is_a?(Numeric) && v.to_i.between?(min, max) end
Try / catch
begin
Concurrent::ThreadPoolExecutor.new(max_threads: n)
rescue ArgumentError => e
raise unless e.message.start_with?('`max_threads` cannot be greater than')
Concurrent::ThreadPoolExecutor.new # default is already the cap
end Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- `max_threads` cannot be greater than #{DEFAULT_MAX_POOL_SIZE
- number of threads must be greater than zero
- `synchronous` cannot be set unless `max_queue` is 0
- `max_threads` cannot be less than #{DEFAULT_MIN_POOL_SIZE}
- `min_threads` cannot be less than #{DEFAULT_MIN_POOL_SIZE}
AI-assisted analysis of ruby-concurrency/concurrent-ruby@0b88d5ff75 (2026-08-21).
Data as JSON: /api/errors/7ccc10f4ac4f03fa.
Report an issue: GitHub.