ruby-grape/grape · warning
Passing a positional options Hash to `desc` is deprecated. P
Error message
Passing a positional options Hash to `desc` is deprecated. Pass keyword arguments instead.
What it means
`desc` now takes keyword arguments. Under Ruby 3 keyword separation, a Hash passed positionally (`desc 'text', { success: Entity }`) no longer lands in the options slot — Grape detects it in the splat, warns through `Grape.deprecator`, and merges it with the keyword options for backwards compatibility. The positional form will be removed in a future release.
Source
Thrown at lib/grape/dsl/desc.rb:55
# @example
#
# desc 'create a user'
# post '/users' do
# # ...
# end
#
# desc 'find a user' do
# detail 'locates the user from the given user ID'
# failure [ [404, 'Couldn\'t find the given user' ] ]
# success User::Entity
# end
# get '/user/:id' do
# # ...
# end
#
def desc(description, *legacy_options, **options, &config_block)
if legacy_options.any?
Grape.deprecator.warn('Passing a positional options Hash to `desc` is deprecated. Pass keyword arguments instead.')
options = legacy_options.first.merge(options)
end
settings =
if config_block
endpoint_config = defined?(configuration) ? configuration : nil
Grape::Util::ApiDescription.new(description, endpoint_config, &config_block).settings
else
options.merge(description:)
end
# Only the route scope is consumed downstream (by +route+ and the
# route's readers, e.g. +http_codes+); the namespace scope was
# write-only, so it is no longer populated.
inheritable_setting.route_description = settings
end
end
end
endView on GitHub (pinned to 22d7975629)
Solutions
- Drop the braces and pass keywords: `desc 'find a user', summary: 'x', success: User::Entity`
- Or use the block form: `desc 'find a user' do ... end`
- Set `Grape.deprecator.behavior = :raise` in the test environment to flush out every remaining call site
Example fix
# before
desc 'find a user', { success: User::Entity, failure: [[404, 'Not Found']] }
# after
desc 'find a user', success: User::Entity, failure: [[404, 'Not Found']] Defensive patterns
Strategy: validation
Validate before calling
# CI guard: turn deprecations into failures so positional-hash `desc` calls cannot slip through Grape.deprecator.behavior = :raise if ENV['CI']
Prevention
- Write `desc 'text', key: value` without braces — never `desc('text', { ... })`
- Run the suite with `Grape.deprecator.behavior = :raise` during upgrades
- Search the codebase for `desc(` with a brace literal as part of major-version upgrades
When it happens
Trigger: `desc 'find a user', { summary: 'x', success: User::Entity }` (explicit braces); `desc('find a user', { failure: [[404, 'Not Found']] })`; any `desc` call whose second positional argument is a Hash.
Common situations: Apps written before the Ruby 3 keyword split; upgrading Grape across a major version that keyword-ified the DSL; code generators that emit hash literals into `desc` calls.
Related errors
- Passing a positional options Hash to `#{method_name}` is dep
- Passing a positional options Hash to `#{method_name}` is dep
- rescue_from #{meta_selector.inspect} does not accept additio
- Either contract or block must be provided
- must supply type for coerce_with
AI-assisted analysis of ruby-grape/grape@22d7975629 (2026-08-21).
Data as JSON: /api/errors/936a1e8a97c41e06.
Report an issue: GitHub.