ruby-grape/grape · error · ArgumentError
Unknown type: #{type}
Error message
Unknown type: #{type} What it means
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.
Source
Thrown at lib/grape/validations/types/dry_type_coercer.rb:26
# but check its type. More information there
# https://dry-rb.org/gems/dry-types/main/built-in-types/
class DryTypeCoercer
extend Grape::Util::FreezeOnNew
class << self
# Returns a collection coercer which corresponds to a given type.
# Example:
#
# collection_coercer_for(Array)
# #=> Grape::Validations::Types::ArrayCoercer
def collection_coercer_for(type)
case type
when Array
ArrayCoercer
when Set
SetCoercer
else
raise ArgumentError, "Unknown type: #{type}"
end
end
# Returns an instance of a coercer for a given type
def coercer_instance_for(type, strict: false)
klass = type.instance_of?(Class) ? PrimitiveCoercer : collection_coercer_for(type)
klass.new(type, strict:)
end
end
def initialize(type, strict: false)
@type = type
@strict = strict
@cache_coercer = strict ? DryTypes::StrictCache : DryTypes::ParamsCache
end
# Coerces the given value to a type which was specified during
# initialization as a type argument.View on GitHub (pinned to 22d7975629)
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]`
Example fix
# before requires :user_id, type: Dry::Types::Params::Integer # after requires :user_id, type: Integer # or wrap a dry-type as a custom type class UserId def self.parse(val) = Dry::Types['coercible.integer'].call(val) end requires :user_id, type: UserId
Defensive patterns
Strategy: type-guard
Validate before calling
def supported_grape_type?(type)
type.instance_of?(Class) || type.is_a?(Array) || type.is_a?(Set)
end
raise ArgumentError, "unsupported type #{type.inspect}" unless supported_grape_type?(decl[:type]) Type guard
def grape_supported_type?(type)
type.instance_of?(Class) || type.is_a?(Array) || type.is_a?(Set)
end
# usage before the DSL:
# raise ArgumentError, "bad type #{t.inspect}" unless grape_supported_type?(t) Try / catch
begin
requires :user_id, type: type_from_config
rescue ArgumentError => e
raise "type #{type_from_config.inspect} is not a Grape type (pass the class, not a symbol/instance/dry-type)"
end Prevention
- 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
When it happens
Trigger: `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).
Common situations: 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`.
Related errors
- type #{type} should support coercion via `[]`
- must supply type for coerce_with
- coerce_with disallowed for type: JSON
- :type may not be supplied with :types
- oneof: requires type: Hash
AI-assisted analysis of ruby-grape/grape@22d7975629 (2026-08-21).
Data as JSON: /api/errors/650dbc21b61d09a1.
Report an issue: GitHub.