{"record":{"id":"650dbc21b61d09a1","repo":"ruby-grape/grape","slug":"unknown-type-type","errorCode":null,"errorMessage":"Unknown type: #{type}","messagePattern":"Unknown type: #(.+?)","errorType":"exception","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"lib/grape/validations/types/dry_type_coercer.rb","lineNumber":26,"sourceCode":"      # but check its type. More information there\n      # https://dry-rb.org/gems/dry-types/main/built-in-types/\n      class DryTypeCoercer\n        extend Grape::Util::FreezeOnNew\n\n        class << self\n          # Returns a collection coercer which corresponds to a given type.\n          # Example:\n          #\n          #    collection_coercer_for(Array)\n          #    #=> Grape::Validations::Types::ArrayCoercer\n          def collection_coercer_for(type)\n            case type\n            when Array\n              ArrayCoercer\n            when Set\n              SetCoercer\n            else\n              raise ArgumentError, \"Unknown type: #{type}\"\n            end\n          end\n\n          # Returns an instance of a coercer for a given type\n          def coercer_instance_for(type, strict: false)\n            klass = type.instance_of?(Class) ? PrimitiveCoercer : collection_coercer_for(type)\n            klass.new(type, strict:)\n          end\n        end\n\n        def initialize(type, strict: false)\n          @type = type\n          @strict = strict\n          @cache_coercer = strict ? DryTypes::StrictCache : DryTypes::ParamsCache\n        end\n\n        # Coerces the given value to a type which was specified during\n        # initialization as a type argument.","sourceCodeStart":8,"sourceCodeEnd":44,"githubUrl":"https://github.com/ruby-grape/grape/blob/22d7975629846a3c0c7bd2b34e140a7a1b4af8f6/lib/grape/validations/types/dry_type_coercer.rb#L8-L44","documentation":"When Grape builds a param coercer it accepts a Class (primitives like Integer/String, Grape special types, custom types with `parse`), an Array or Set type specifier (`[Integer]`, `Set[Integer]`), or an Array of classes for unions. Anything else — a Symbol, a String, a dry-types type object, or an instance instead of a class — falls through to `DryTypeCoercer.collection_coercer_for`, which only knows Array and Set and raises `ArgumentError: Unknown type: <value>` at API-definition time.","triggerScenarios":"`requires :count, type: :integer` (symbol instead of class); `requires :n, type: 'Integer'` (string); `requires :t, type: Dry::Types::Params::Integer` (a dry-types object, not a Class); `requires :v, type: MyType.new` (instance instead of the class).","commonSituations":"Coming from Rails conventions where symbols name types; assuming Grape accepts dry-types objects directly under `type:`; passing the parsed instance because the custom-type docs show instances being returned from `parse`.","solutions":["Pass the class itself: `type: Integer`, `type: String`, `type: JSON`","For custom value objects, pass the class and implement the Grape custom-type contract (class-level `parse`, optional `parsed?`)","To reuse a dry-type, wrap it in a class with `def self.parse(val)` that delegates to the dry type, then use `type: YourWrapper`","For collections use `[ElementType]` or `Set[ElementType]`"],"exampleFix":"# before\nrequires :user_id, type: Dry::Types::Params::Integer\n\n# after\nrequires :user_id, type: Integer\n\n# or wrap a dry-type as a custom type\nclass UserId\n  def self.parse(val) = Dry::Types['coercible.integer'].call(val)\nend\nrequires :user_id, type: UserId","handlingStrategy":"type-guard","validationCode":"def supported_grape_type?(type)\n  type.instance_of?(Class) || type.is_a?(Array) || type.is_a?(Set)\nend\n\nraise ArgumentError, \"unsupported type #{type.inspect}\" unless supported_grape_type?(decl[:type])","typeGuard":"def grape_supported_type?(type)\n  type.instance_of?(Class) || type.is_a?(Array) || type.is_a?(Set)\nend\n\n# usage before the DSL:\n# raise ArgumentError, \"bad type #{t.inspect}\" unless grape_supported_type?(t)","tryCatchPattern":"begin\n  requires :user_id, type: type_from_config\nrescue ArgumentError => e\n  raise \"type #{type_from_config.inspect} is not a Grape type (pass the class, not a symbol/instance/dry-type)\"\nend","preventionTips":["Always pass classes (`Integer`, `String`, custom classes), never symbols or strings","Wrap dry-types in a custom type class with `def self.parse(val)` instead of passing the dry-type object","For collections use `[ElementType]` / `Set[ElementType]`, and pass the class — not an instance — for custom types"],"tags":["grape","params","types","coercion","dry-types","argumenterror"],"backgroundTag":"unknown-parameter-type","analyzedSha":"22d7975629846a3c0c7bd2b34e140a7a1b4af8f6","analyzedAt":"2026-08-21T17:03:54.627Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}