{"record":{"id":"e5b4cf0720b06d66","repo":"ruby-grape/grape","slug":"except-values-proc-must-have-arity-of-zero-use-va","errorCode":null,"errorMessage":"except_values Proc must have arity of zero (use values: with a one-arity predicate for per-element checks)","messagePattern":"except_values Proc must have arity of zero \\(use values: with a one-arity predicate for per-element checks\\)","errorType":"exception","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"lib/grape/validations/validators/except_values_validator.rb","lineNumber":13,"sourceCode":"# frozen_string_literal: true\n\nmodule Grape\n  module Validations\n    module Validators\n      class ExceptValuesValidator < Base\n        default_message_key :except_values\n\n        def initialize(attrs, options, required, scope, opts)\n          super\n          except = option_value\n          except_proc = except.is_a?(Proc)\n          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?\n\n          # Zero-arity procs (e.g. -> { User.pluck(:role) }) must be called per-request,\n          # not at definition time, so they are wrapped in a lambda to defer execution.\n          @excepts_call = except_proc ? except : -> { except }\n        end\n\n        def validate_param!(attr_name, params)\n          return unless hash_like?(params) && params.key?(attr_name)\n\n          excepts = @excepts_call.call\n          return if excepts.nil?\n\n          param_array = params[attr_name].nil? ? [nil] : Array.wrap(params[attr_name])\n          return if param_array.none? { |param| excepts.include?(param) }\n\n          validation_error!(attr_name)\n        end\n      end","sourceCodeStart":1,"sourceCodeEnd":31,"githubUrl":"https://github.com/ruby-grape/grape/blob/22d7975629846a3c0c7bd2b34e140a7a1b4af8f6/lib/grape/validations/validators/except_values_validator.rb#L1-L31","documentation":"`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.","triggerScenarios":"`except_values: ->(role) { role != 'admin' }` (one-arity predicate); `except_values: method(:blocked_roles)` where the method expects arguments; `except_values: proc { |x| !x.blank? }`.","commonSituations":"Copying a `values:`-style predicate into `except_values:`; reusing a validation proc from another library that expects the element as its argument.","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]`"],"exampleFix":"# before\nexcept_values: ->(role) { role != 'admin' }\n\n# after — per-request excluded list (zero-arity)\nexcept_values: -> { Role.blocked.pluck(:name) }\n\n# after — per-element allow check (belongs under values:)\nvalues: ->(v) { ALLOWED_ROLES.include?(v) }","handlingStrategy":"type-guard","validationCode":"def except_values_proc_ok?(opt)\n  !opt.is_a?(Proc) || opt.arity.zero?\nend\n\nraise ArgumentError, 'except_values proc must return the list (zero arity)' unless except_values_proc_ok?(xopts[:except_values])","typeGuard":"def zero_arity_proc?(opt)\n  !opt.is_a?(Proc) || opt.arity.zero?\nend\n\n# per-element predicates belong under values:, where arity one is required:\ndef one_arity_predicate?(opt)\n  !opt.is_a?(Proc) || opt.arity == 1\nend","tryCatchPattern":"begin\n  optional :role, type: String, except_values: except_proc\nrescue ArgumentError => e\n  raise \"use values: with a one-arity predicate for per-element checks: #{e.message}\"\nend","preventionTips":["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"],"tags":["grape","params","except-values","proc-arity","argumenterror"],"backgroundTag":"callback-arity-mismatch","analyzedSha":"22d7975629846a3c0c7bd2b34e140a7a1b4af8f6","analyzedAt":"2026-08-21T17:03:54.627Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}