ruby-concurrency/concurrent-ruby · error · ArgumentError
:initial_capacity must be a positive Integer
Error message
:initial_capacity must be a positive Integer
What it means
Concurrent::Map.new accepts tuning options modeled on Java's ConcurrentHashMap. validate_options_hash! (map.rb:344-346) rejects :initial_capacity unless it is an Integer >= 0; a negative number, Float, String, or other non-Integer raises ArgumentError at construction time, before any entry is stored.
Source
Thrown at lib/concurrent-ruby/concurrent/map.rb:343
private
def raise_fetch_no_key
raise KeyError, 'key not found'
end
def initialize_copy(other)
super
populate_from(other)
end
def populate_from(hash)
hash.each_pair { |k, v| self[k] = v }
self
end
def validate_options_hash!(options)
if (initial_capacity = options[:initial_capacity]) && (!initial_capacity.kind_of?(Integer) || initial_capacity < 0)
raise ArgumentError, ":initial_capacity must be a positive Integer"
end
if (load_factor = options[:load_factor]) && (!load_factor.kind_of?(Numeric) || load_factor <= 0 || load_factor > 1)
raise ArgumentError, ":load_factor must be a number between 0 and 1"
end
end
end
end
View on GitHub (pinned to 0b88d5ff75)
Solutions
- Pass a non-negative Integer: Concurrent::Map.new(initial_capacity: 64).
- Cast untrusted config at the boundary: initial_capacity: cfg.fetch('initial_capacity', 0).to_i.
- Clamp computed values: [capacity, 0].max so the constructor never sees a negative number.
Example fix
# before
map = Concurrent::Map.new(initial_capacity: cfg['initial_capacity']) # '64' or -1 raises ArgumentError
# after
map = Concurrent::Map.new(initial_capacity: [cfg.fetch('initial_capacity', 0).to_i, 0].max) Defensive patterns
Strategy: validation
Validate before calling
def map_capacity(raw) cap = raw.is_a?(Integer) ? raw : raw.to_i raise ArgumentError, ':initial_capacity must be an Integer >= 0' unless cap >= 0 cap end Concurrent::Map.new(initial_capacity: map_capacity(cfg['initial_capacity']))
Prevention
- Coerce config-sourced numbers to Integer at the config boundary.
- Do not port Java float capacities verbatim; this API is Integer-only.
- Unit-test Map construction with your real production config values.
When it happens
Trigger: Concurrent::Map.new(initial_capacity: -1); initial_capacity: 10.0 (Float, not Integer); initial_capacity: '100' read from YAML/ENV/JSON without casting to Integer.
Common situations: Porting Java ConcurrentHashMap tuning parameters verbatim; loading options from stringly-typed config; passing nil or a computed value that evaluates to a negative number.
Related errors
- :load_factor must be a number between 0 and 1
- executor not recognized by '#{executor_identifier}'
- unbuffered channels cannot have a capacity
- capacity must be at least 1 for this buffer type
- no block given
AI-assisted analysis of ruby-concurrency/concurrent-ruby@0b88d5ff75 (2026-08-21).
Data as JSON: /api/errors/2f3473aa84ed672e.
Report an issue: GitHub.