ruby-concurrency/concurrent-ruby · error · ArgumentError
`max_threads` cannot be less than #{DEFAULT_MIN_POOL_SIZE}
Error message
`max_threads` cannot be less than #{DEFAULT_MIN_POOL_SIZE} What it means
On JRuby, ThreadPoolExecutor coerces max_threads with to_i and raises ArgumentError when it is below DEFAULT_MIN_POOL_SIZE (0), i.e. when it is negative. This guards the java.util.concurrent.ThreadPoolExecutor constructor from impossible pool sizes.
Source
Thrown at lib/concurrent-ruby/concurrent/executor/java_thread_pool_executor.rb:118
end
# @!macro thread_pool_executor_method_prune_pool
def prune_pool
deprecated "#prune_pool has no effect and will be removed in the next release."
end
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("`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
raise ArgumentError.new("#{fallback_policy} is not a valid fallback policy") unless FALLBACK_POLICY_CLASSES.include?(@fallback_policy)
if @max_queue == 0
if @synchronous
queue = java.util.concurrent.SynchronousQueue.new
else
queue = java.util.concurrent.LinkedBlockingQueue.new
end
else
queue = java.util.concurrent.LinkedBlockingQueue.new(@max_queue)
end
@executor = java.util.concurrent.ThreadPoolExecutor.new(
min_length,
max_length,View on GitHub (pinned to 0b88d5ff75)
Solutions
- Validate before constructing: n = Integer(opts[:max_threads]); raise if n < 0
- Clamp computed sizes: [[computed, 0].max, 2_147_483_647].min
- Use a positive default when core detection fails instead of propagating a negative
Example fix
# before Concurrent::ThreadPoolExecutor.new(max_threads: detected_cores - 2) # after max_threads = [[detected_cores - 2, 0].max, 2_147_483_647].min Concurrent::ThreadPoolExecutor.new(max_threads: max_threads)
Defensive patterns
Strategy: validation
Validate before calling
max_threads = Integer(cfg[:max_threads])
raise ArgumentError, "max_threads must be >= 0, got #{max_threads}" if max_threads.negative?
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 less than')
Concurrent::ThreadPoolExecutor.new(max_threads: [n, 0].max)
end Prevention
- Clamp ENV/core-count derived sizes: [computed, 0].max
- Use Integer() parsing so junk values fail loudly at the config boundary
- Add a config spec asserting thread counts are non-negative
When it happens
Trigger: max_threads: -1 (or any negative) on JRuby; string '-8' coerced by to_i; capacity math like available_cores - 2 when the core count is unknown/under-reported and the expression goes negative.
Common situations: Sizing formulas based on CPU detection that return negative values in containers or CI; negative sentinels meaning 'unbounded'; sign typos in config.
Related errors
- `synchronous` cannot be set unless `max_queue` is 0
- `max_threads` cannot be greater than #{DEFAULT_MAX_POOL_SIZE
- `min_threads` cannot be less than #{DEFAULT_MIN_POOL_SIZE}
- `min_threads` cannot be more than `max_threads`
- #{fallback_policy} is not a valid fallback policy
AI-assisted analysis of ruby-concurrency/concurrent-ruby@0b88d5ff75 (2026-08-21).
Data as JSON: /api/errors/5c0af1b4a2c9deb2.
Report an issue: GitHub.