ruby-concurrency/concurrent-ruby · error · RangeError
#{value} is less than the maximum value of #{MIN_VALUE}
Error message
#{value} is less than the maximum value of #{MIN_VALUE} What it means
The lower-bound twin of the maximum check: values below -(2**62) cannot be held in a native fixnum slot, so storing them into AtomicFixnum (new, value=, update) or the count-taking constructors of Semaphore/CountDownLatch/CyclicBarrier raises RangeError. Ruby's arbitrary-precision arithmetic happily produces such values right up to the store.
Source
Thrown at lib/concurrent-ruby/concurrent/utility/native_integer.rb:19
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
def ensure_integer_and_bounds(value)
ensure_integer value
ensure_upper_bound value
ensure_lower_bound value
end
def ensure_positive(value)View on GitHub (pinned to 0b88d5ff75)
Solutions
- Validate before storing: raise RangeError, 'below native minimum' if value < Concurrent::Utility::NativeInteger::MIN_VALUE
- Clamp when undershoot has a defined floor: value = [value, Concurrent::Utility::NativeInteger::MIN_VALUE].max
- Move unbounded arithmetic into plain Integers + Mutex, using AtomicFixnum only where values provably stay in range
Example fix
# before balance = Concurrent::AtomicFixnum.new(-(2**62) - 1) # RangeError # after min = Concurrent::Utility::NativeInteger::MIN_VALUE raise RangeError, 'balance underflow' if amount < min balance = Concurrent::AtomicFixnum.new(amount)
Defensive patterns
Strategy: validation
Validate before calling
NI = Concurrent::Utility::NativeInteger
raise RangeError, "#{value} below atomic counter range" if value.is_a?(Integer) && value < NI::MIN_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::MIN_VALUE # explicit floor + alert end
Prevention
- Check the MIN_VALUE bound before storing negated or deeply negative values
- Run domain floor checks (e.g. balance >= 0) before arithmetic reaches the atomic
- Alert on saturation instead of letting it pass silently
When it happens
Trigger: Concurrent::AtomicFixnum.new(-(2**62)); counter.update { |v| v - 2**62 } from a subtraction of big aggregates; negating a large positive counter; semaphore/latch counts computed as differences of big numbers.
Common situations: Balance/credit arithmetic going deeply negative before a domain check runs; mirroring large external counters (negative deltas); JRuby-to-MRI porting where the native range differs.
Related errors
- #{value} is greater than the maximum value of #{MAX_VALUE}
- #{value} is not an Integer
- no block given
- Not all dependencies are IVars. Dependencies: #{ inputs.insp
- no block given
AI-assisted analysis of ruby-concurrency/concurrent-ruby@0b88d5ff75 (2026-08-21).
Data as JSON: /api/errors/0e7b49af46868fc1.
Report an issue: GitHub.