ruby-concurrency/concurrent-ruby · error · RangeError
#{value} is greater than the maximum value of #{MAX_VALUE}
Error message
#{value} is greater than the maximum value of #{MAX_VALUE} What it means
Concurrent::Utility::NativeInteger guards native-backed primitives (AtomicFixnum, Semaphore, CountDownLatch, CyclicBarrier) against values that exceed what a native fixnum slot holds: 2**62 - 1 on 64-bit MRI. Ruby Integers are arbitrary precision, so large results compute silently and only blow up when stored into one of these primitives as RangeError. AtomicFixnum.new, AtomicFixnum#value=, and #update all pass through this check.
Source
Thrown at lib/concurrent-ruby/concurrent/utility/native_integer.rb:12
module Concurrent
# @!visibility private
module Utility
# @private
module NativeInteger
# http://stackoverflow.com/questions/535721/ruby-max-integer
MIN_VALUE = -(2**(0.size * 8 - 2))
MAX_VALUE = (2**(0.size * 8 - 2) - 1)
def ensure_upper_bound(value)
if value > MAX_VALUE
raise RangeError.new("#{value} is greater than the maximum value of #{MAX_VALUE}")
end
value
end
def ensure_lower_bound(value)
if value < MIN_VALUE
raise RangeError.new("#{value} is less than the maximum value of #{MIN_VALUE}")
end
value
end
def ensure_integer(value)
unless value.is_a?(Integer)
raise ArgumentError.new("#{value} is not an Integer")
end
value
end
View on GitHub (pinned to 0b88d5ff75)
Solutions
- Validate before storing: raise RangeError, 'counter overflow' if value > Concurrent::Utility::NativeInteger::MAX_VALUE
- Keep oversized counters in a plain Integer guarded by a Mutex or use two counters (high/low words) instead of AtomicFixnum
- Clamp if saturation is acceptable: value = [value, MAX_VALUE].min (document the saturation)
Example fix
# before counter = Concurrent::AtomicFixnum.new(2**63) # RangeError # after max = Concurrent::Utility::NativeInteger::MAX_VALUE raise RangeError, 'id too large for atomic counter' if id > max counter = Concurrent::AtomicFixnum.new(id)
Defensive patterns
Strategy: validation
Validate before calling
NI = Concurrent::Utility::NativeInteger
raise RangeError, "#{value} exceeds atomic counter range" if value.is_a?(Integer) && value > NI::MAX_VALUE
Concurrent::AtomicFixnum.new(value) Type guard
def native_int?(v)
v.is_a?(Integer) &&
v.between?(Concurrent::Utility::NativeInteger::MIN_VALUE,
Concurrent::Utility::NativeInteger::MAX_VALUE)
end Try / catch
begin counter.value = next_value rescue RangeError counter.value = Concurrent::Utility::NativeInteger::MAX_VALUE # explicit saturation + alert end
Prevention
- Check against NativeInteger::MAX_VALUE before storing big computed values
- Keep unbounded counters in plain Integer + Mutex; use AtomicFixnum only for provably bounded values
- Add overflow asserts in update blocks that multiply or shift
When it happens
Trigger: Concurrent::AtomicFixnum.new(2**63); counter.update { |v| v * 2 } crossing the bound; bit masks like (1 << 63) stored into an AtomicFixnum; IDs/counters aggregated over a long-lived process.
Common situations: Shard/snowflake-style IDs or epoch-millisecond counters pushed into AtomicFixnum; multiplying large aggregates in update blocks; porting code from JRuby (where native limits differ) to MRI.
Related errors
- #{value} is less than the maximum value of #{MIN_VALUE}
- `max_threads` cannot be greater than #{DEFAULT_MAX_POOL_SIZE
- `max_threads` cannot be greater than #{DEFAULT_MAX_POOL_SIZE
- #{value} is not an Integer
- no block given
AI-assisted analysis of ruby-concurrency/concurrent-ruby@0b88d5ff75 (2026-08-21).
Data as JSON: /api/errors/4dd486c5c15ba89d.
Report an issue: GitHub.