ruby-grape/grape · error · ArgumentError
except_values Proc must have arity of zero (use values: with
Error message
except_values Proc must have arity of zero (use values: with a one-arity predicate for per-element checks)
What it means
`except_values:` accepts a static list or a Proc. The Proc form is evaluated per request with no arguments (so fresh data such as a DB query is used), which means it must have arity zero. A Proc with parameters would be called with none and return garbage, so the validator raises ArgumentError at definition time. Per-element predicates (arity one) belong under `values:`, which the message explicitly points you to.
Source
Thrown at lib/grape/validations/validators/except_values_validator.rb:13
# frozen_string_literal: true
module Grape
module Validations
module Validators
class ExceptValuesValidator < Base
default_message_key :except_values
def initialize(attrs, options, required, scope, opts)
super
except = option_value
except_proc = except.is_a?(Proc)
raise ArgumentError, 'except_values Proc must have arity of zero (use values: with a one-arity predicate for per-element checks)' if except_proc && !except.arity.zero?
# Zero-arity procs (e.g. -> { User.pluck(:role) }) must be called per-request,
# not at definition time, so they are wrapped in a lambda to defer execution.
@excepts_call = except_proc ? except : -> { except }
end
def validate_param!(attr_name, params)
return unless hash_like?(params) && params.key?(attr_name)
excepts = @excepts_call.call
return if excepts.nil?
param_array = params[attr_name].nil? ? [nil] : Array.wrap(params[attr_name])
return if param_array.none? { |param| excepts.include?(param) }
validation_error!(attr_name)
end
endView on GitHub (pinned to 22d7975629)
Solutions
- Use a zero-arity Proc that RETURNS the excluded list: `except_values: -> { Role.blocked.pluck(:name) }`
- For per-element allow checks, use `values:` with a one-arity predicate: `values: ->(v) { ALLOWED.include?(v) }` (truthy = allowed)
- Use a plain array when the excluded set is static: `except_values: %w[admin root]`
Example fix
# before
except_values: ->(role) { role != 'admin' }
# after — per-request excluded list (zero-arity)
except_values: -> { Role.blocked.pluck(:name) }
# after — per-element allow check (belongs under values:)
values: ->(v) { ALLOWED_ROLES.include?(v) } Defensive patterns
Strategy: type-guard
Validate before calling
def except_values_proc_ok?(opt) !opt.is_a?(Proc) || opt.arity.zero? end raise ArgumentError, 'except_values proc must return the list (zero arity)' unless except_values_proc_ok?(xopts[:except_values])
Type guard
def zero_arity_proc?(opt) !opt.is_a?(Proc) || opt.arity.zero? end # per-element predicates belong under values:, where arity one is required: def one_arity_predicate?(opt) !opt.is_a?(Proc) || opt.arity == 1 end
Try / catch
begin
optional :role, type: String, except_values: except_proc
rescue ArgumentError => e
raise "use values: with a one-arity predicate for per-element checks: #{e.message}"
end Prevention
- Reserve zero-arity procs for except_values (they RETURN the list) and one-arity predicates for values (they ACCEPT an element)
- For static exclusion sets, use plain arrays
- Add a lint spec over reusable validation procs asserting their arity matches their option key
When it happens
Trigger: `except_values: ->(role) { role != 'admin' }` (one-arity predicate); `except_values: method(:blocked_roles)` where the method expects arguments; `except_values: proc { |x| !x.blank? }`.
Common situations: Copying a `values:`-style predicate into `except_values:`; reusing a validation proc from another library that expects the element as its argument.
Related errors
- must supply type for coerce_with
- coerce_with disallowed for type: JSON
- oneof: requires type: Hash
- oneof: must be a non-empty Array of blocks
- oneof: each variant must be a Proc
AI-assisted analysis of ruby-grape/grape@22d7975629 (2026-08-21).
Data as JSON: /api/errors/e5b4cf0720b06d66.
Report an issue: GitHub.