ruby-concurrency/concurrent-ruby · error · ArgumentError
`min_threads` cannot be more than `max_threads`
Error message
`min_threads` cannot be more than `max_threads`
What it means
On JRuby, ThreadPoolExecutor raises ArgumentError when min_threads exceeds max_threads. The pool would otherwise be unable to satisfy both bounds, so construction fails fast during ns_initialize.
Source
Thrown at lib/concurrent-ruby/concurrent/executor/java_thread_pool_executor.rb:121
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,
idletime,
java.util.concurrent.TimeUnit::SECONDS,
queue,View on GitHub (pinned to 0b88d5ff75)
Solutions
- Set max_threads first and derive min_threads from it: min = [wanted_min, max].min
- Validate the pair before construction and raise with both values in the message
- Keep both values in one config block so they are reviewed together
Example fix
# before Concurrent::ThreadPoolExecutor.new(min_threads: 10, max_threads: 5) # after max_threads = 5 min_threads = [10, max_threads].min Concurrent::ThreadPoolExecutor.new(min_threads: min_threads, max_threads: max_threads)
Defensive patterns
Strategy: validation
Validate before calling
max_threads = Integer(cfg.fetch(:max_threads, 2_147_483_647))
min_threads = [Integer(cfg.fetch(:min_threads, 0)), max_threads].min
raise ArgumentError, "min_threads #{min_threads} > max_threads #{max_threads}" if min_threads > max_threads
Concurrent::ThreadPoolExecutor.new(min_threads: min_threads, max_threads: max_threads) Type guard
def coherent_pool_bounds?(min, max) min.is_a?(Integer) && max.is_a?(Integer) && min >= 0 && max >= min && max <= 2_147_483_647 end
Try / catch
begin
Concurrent::ThreadPoolExecutor.new(min_threads: mn, max_threads: mx)
rescue ArgumentError => e
raise unless e.message.start_with?('`min_threads` cannot be more than')
Concurrent::ThreadPoolExecutor.new(min_threads: [mn, mx].min, max_threads: mx)
end Prevention
- Derive min_threads from max_threads in config templates
- Keep both keys in one reviewed config block
- Add a spec asserting min <= max across environment overrides
When it happens
Trigger: min_threads: 10, max_threads: 5 on JRuby; independently configured values (MIN defaulting high while MAX is lowered); YAML overrides applied in the wrong precedence order.
Common situations: Two ENV vars or YAML keys maintained by different teams drifting apart; lowering max_threads in an environment-specific override while min_threads comes from a shared default; renames that swap the two keys.
Related errors
- `synchronous` cannot be set unless `max_queue` is 0
- `max_threads` cannot be less than #{DEFAULT_MIN_POOL_SIZE}
- `max_threads` cannot be greater than #{DEFAULT_MAX_POOL_SIZE
- `min_threads` cannot be less than #{DEFAULT_MIN_POOL_SIZE}
- #{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/9b7f33231df0c319.
Report an issue: GitHub.