{"record":{"id":"9771a44549862d5c","repo":"ruby-grape/grape","slug":"is-cannot-be-combined-with-min-or-max","errorCode":null,"errorMessage":"is cannot be combined with min or max","messagePattern":"is cannot be combined with min or max","errorType":"exception","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"lib/grape/validations/validators/length_validator.rb","lineNumber":17,"sourceCode":"# frozen_string_literal: true\n\nmodule Grape\n  module Validations\n    module Validators\n      class LengthValidator < Base\n        def initialize(attrs, options, required, scope, opts)\n          super\n\n          @min, @max, @is = options.values_at(:min, :max, :is)\n          validate_boundary!(:min, @min)\n          validate_boundary!(:max, @max)\n          raise ArgumentError, \"min #{@min} cannot be greater than max #{@max}\" if @min && @max && @min > @max\n\n          return if @is.nil?\n          raise ArgumentError, 'is must be an integer greater than zero' unless @is.is_a?(Integer) && @is.positive?\n          raise ArgumentError, 'is cannot be combined with min or max' unless @min.nil? && @max.nil?\n        end\n\n        def validate_param!(attr_name, params)\n          return unless hash_like?(params)\n\n          param = params[attr_name]\n\n          return unless param.respond_to?(:length)\n\n          return unless (!@min.nil? && param.length < @min) || (!@max.nil? && param.length > @max) || (!@is.nil? && param.length != @is)\n\n          validation_error!(attr_name, message do\n            if @min && @max\n              translate(:length, min: @min, max: @max)\n            elsif @min\n              translate(:length_min, min: @min)\n            elsif @max\n              translate(:length_max, max: @max)","sourceCodeStart":1,"sourceCodeEnd":35,"githubUrl":"https://github.com/ruby-grape/grape/blob/22d7975629846a3c0c7bd2b34e140a7a1b4af8f6/lib/grape/validations/validators/length_validator.rb#L1-L35","documentation":"`is:` (exact length) and `min:`/`max:` (bounds) are mutually exclusive ways to constrain length — combining an exact value with a range is either redundant or contradictory. The LengthValidator raises ArgumentError at definition time when both appear in one `length:` option hash.","triggerScenarios":"`length: { is: 5, min: 3 }`; `length: { is: 5, max: 8 }`; merged option hashes that combine an exact rule with bounds.","commonSituations":"Layering shared defaults such as `{ min: 1, max: 100 }` onto declarations that already carry `is:`; incremental edits that add a bound to an existing exact rule.","solutions":["Keep `is:` alone for exact lengths","Express exactness as `min: 5, max: 5` if you must merge with bound-style configs","Delete whichever constraint was not intended"],"exampleFix":"# before\nrequires :zip, type: String, length: { is: 5, min: 1 }\n\n# after\nrequires :zip, type: String, length: { is: 5 }","handlingStrategy":"validation","validationCode":"def is_isolated?(length_opts)\n  length_opts[:is].nil? || (length_opts[:min].nil? && length_opts[:max].nil?)\nend\n\nraise 'length is: cannot be combined with min/max' unless is_isolated?(merged_length_opts)","typeGuard":null,"tryCatchPattern":"begin\n  requires :zip, type: String, length: length_opts\nrescue ArgumentError => e\n  raise \"length options conflict after merging defaults: #{e.message}\"\nend","preventionTips":["Do not merge bound-style defaults into declarations that use `is:`","Pick one mental model per rule: exact (`is:`) or range (`min:`/`max:`)","Express unavoidable exact-plus-bounds as `min: N, max: N`"],"tags":["grape","params","length-validation","argumenterror","conflicting-options"],"backgroundTag":"conflicting-options","analyzedSha":"22d7975629846a3c0c7bd2b34e140a7a1b4af8f6","analyzedAt":"2026-08-21T17:03:54.627Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}