ruby-grape/grape · error · ArgumentError
#{name} must be an integer greater than or equal to zero
Error message
#{name} must be an integer greater than or equal to zero What it means
Each `min:`/`max:` bound passed to the `length` validator must be a non-negative Integer (`validate_boundary!`). Negative numbers and non-integers (strings, floats) are rejected with ArgumentError at definition time — these are declaration bugs, not per-request validation failures.
Source
Thrown at lib/grape/validations/validators/length_validator.rb:45
return unless (!@min.nil? && param.length < @min) || (!@max.nil? && param.length > @max) || (!@is.nil? && param.length != @is)
validation_error!(attr_name, message do
if @min && @max
translate(:length, min: @min, max: @max)
elsif @min
translate(:length_min, min: @min)
elsif @max
translate(:length_max, max: @max)
else
translate(:length_is, is: @is)
end
end)
end
private
def validate_boundary!(name, val)
raise ArgumentError, "#{name} must be an integer greater than or equal to zero" if !val.nil? && (!val.is_a?(Integer) || val.negative?)
end
end
end
end
end
View on GitHub (pinned to 22d7975629)
Solutions
- Pass non-negative Integers: `length: { min: 2, max: 10 }`
- Convert config-sourced values before the DSL sees them: `min: cfg[:min].to_i` and clamp negatives
- Omit the key entirely rather than passing 0 when no lower bound is wanted
Example fix
# before
requires :bio, type: String, length: { min: '10', max: 500 }
# after
requires :bio, type: String, length: { min: 10, max: 500 } Defensive patterns
Strategy: validation
Validate before calling
def valid_bound?(value) value.nil? || (value.is_a?(Integer) && !value.negative?) end def valid_length_boundaries?(length_opts) valid_bound?(length_opts[:min]) && valid_bound?(length_opts[:max]) end
Try / catch
begin
requires :bio, type: String, length: { min: cfg[:min], max: cfg[:max] }
rescue ArgumentError => e
raise "length bounds must be non-negative Integers: #{e.message}"
end Prevention
- Convert ENV/config bounds with `.to_i` and reject negatives before the DSL sees them
- Omit a bound key rather than passing 0 to mean 'unbounded'
- Keep length rules in one place per endpoint instead of scattering partial configs
When it happens
Trigger: `length: { min: -1 }`; `length: { max: '10' }` (string from env/config); `length: { min: 3.5 }` (float).
Common situations: ENV-sourced bounds passed as strings without conversion; floats copied in from calculators or other validator configs.
Related errors
- is must be an integer greater than zero
- min #{@min} cannot be greater than max #{@max}
- is cannot be combined with min or max
- must supply type for coerce_with
- coerce_with disallowed for type: JSON
AI-assisted analysis of ruby-grape/grape@22d7975629 (2026-08-21).
Data as JSON: /api/errors/0df78deb5fe0d042.
Report an issue: GitHub.