{"record":{"id":"90ce2aa6580ec367","repo":"ruby-grape/grape","slug":"type-may-not-be-supplied-with-types","errorCode":null,"errorMessage":":type may not be supplied with :types","messagePattern":":type may not be supplied with :types","errorType":"exception","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"lib/grape/validations/validations_spec.rb","lineNumber":43,"sourceCode":"      # Keys consumed by the spec itself; must NOT be dispatched as validators\n      # by the caller. Documentation-only keys are filtered through a separate\n      # set so that dual-purpose keys (length, default, values, except_values)\n      # aren't accidentally swallowed.\n      SPEC_CONSUMED_KEYS = %i[\n        type types coerce coerce_with coerce_message\n        presence message\n        fail_fast\n        desc description documentation\n      ].freeze\n\n      attr_reader :raw, :coerce_type, :coerce_method, :coerce_message, :presence_options, :values, :except_values, :default, :allow_blank, :fail_fast, :shared_opts, :validator_entries\n\n      def self.from(validations)\n        new(validations)\n      end\n\n      def initialize(raw)\n        raise ArgumentError, ':type may not be supplied with :types' if raw.key?(:type) && raw.key?(:types)\n\n        @raw = raw\n        @coerce_type, @coerce_message, @coerce_method = parse_coerce(raw)\n        @values = resolve_value(raw[:values])\n        @except_values = resolve_value(raw[:except_values])\n        @default = raw[:default]\n        @presence_options = raw[:presence]\n        @allow_blank = resolve_value(raw[:allow_blank])\n        @fail_fast = raw[:fail_fast] || false\n\n        @guessed_coerce_type = guess_coerce_type(declared_coerce_type, @values, @except_values)\n        @shared_opts = { allow_blank: @allow_blank, fail_fast: @fail_fast }.freeze\n        @validator_entries = build_validator_entries(raw)\n\n        validate!\n\n        freeze\n      end","sourceCodeStart":25,"sourceCodeEnd":61,"githubUrl":"https://github.com/ruby-grape/grape/blob/22d7975629846a3c0c7bd2b34e140a7a1b4af8f6/lib/grape/validations/validations_spec.rb#L25-L61","documentation":"`type:` declares a single coercion target; `types:` declares a union of allowed types. They are mutually exclusive — a param cannot be coerced to exactly one type and to several types at once — so `ValidationsSpec#initialize` raises ArgumentError the moment a `requires`/`optional` declaration carries both keys.","triggerScenarios":"`requires :id, type: Integer, types: [Integer, String]`; merging a shared defaults hash containing `type:` into a declaration that adds `types:`; generated declarations where both keys slip in.","commonSituations":"Refactoring a single-typed param into a union and forgetting to delete `type:`; `DEFAULT_OPTS = { type: String }.freeze` merged per-param with a declaration that also passes `types:`.","solutions":["Delete `:type` and keep `types:` for union declarations","When merging defaults, strip the stale key: `decl = defaults.merge(decl); decl.except!(:type) if decl.key?(:types)`","Mount every endpoint in a spec so load-time declaration errors surface in CI rather than at production boot"],"exampleFix":"# before\nrequires :id, type: Integer, types: [Integer, String]\n\n# after\nrequires :id, types: [Integer, String]","handlingStrategy":"validation","validationCode":"def assert_no_type_and_types!(opts)\n  return unless opts.key?(:type) && opts.key?(:types)\n\n  raise ArgumentError, ':type and :types are mutually exclusive (got both in ' + opts.inspect + ')'\nend","typeGuard":null,"tryCatchPattern":"begin\n  requires :id, **merged_opts\nrescue ArgumentError => e\n  raise \"declaration carries both :type and :types after merging defaults: #{e.message}\"\nend","preventionTips":["Never merge a `type:`-bearing defaults hash into declarations that use `types:`","Prefer a single canonical key in shared macros; normalize to `types:` at the boundary","Mount every endpoint in a spec so mutually exclusive keys fail at load time in CI"],"tags":["grape","params","types","validation","argumenterror","dsl"],"backgroundTag":"conflicting-options","analyzedSha":"22d7975629846a3c0c7bd2b34e140a7a1b4af8f6","analyzedAt":"2026-08-21T17:03:54.627Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}