Skip to content

Keep a String error message's status when the route names a failure entity - #2953

Merged
ericproulx merged 1 commit into
masterfrom
fix/failure-entity-string-message
Sep 19, 2026
Merged

ericproulx merged 1 commit into
masterfrom
fix/failure-entity-string-message

Conversation

@ericproulx

@ericproulx ericproulx commented Sep 18, 2026

Copy link
Copy Markdown
Contributor

Summary

ErrorFormatter::Base#present applies the entity that a route's failure codes name for the response status to whatever error! was given. An entity that exposes attributes can't read any off a String, so this raises while rendering and the failsafe answers 500 in place of the requested status:

desc 'Get a thing', failure: [[401, 'Unauthorized', API::Error]]
get '/thing' do
  error!('Unauthorized', 401) # => 500 Internal Server Error
end

The failure block method and the http_codes: keyword have always behaved this way. #2949 (unreleased) made the failure: keyword present too, which is the spelling grape-swagger's README recommends (failure: [[401, 'KittenBitesError', Entities::BadKitten]]). So on master, an API that documents its 401 that way and calls error! with a String now gets a 500 for every 401. 4.0.1 answered 401.

The failure entities document a structured error body, and every README example passes a Hash to error!. A String message is therefore now left to #wrap_message and renders the same way it does when no entity is declared. Hash and object messages are presented as before. with: and a class's own Entity are untouched.

error! given master this PR
{ code: 'x', message: 'm' } 401 presented 401 presented
an object 401 presented 401 presented
'Unauthorized' (any of the three spellings) 500 401 {"error":"Unauthorized"}

Backward compatibility

An entity written to take the String itself (expose(:message) { |message, _| message }) and declared through the block method or http_codes: used to present String messages. It no longer receives them. UPGRADING shows moving it to a Hash message.

Test plan

  • Present an error response with the entity a desc failure keyword names #2949's three-spelling loop in endpoint_spec.rb gains a String-message example. All three fail on master and pass here.
  • spec/integration/grape_entity/entity_spec.rb covers the same case with a real Grape::Entity. It fails on master and passes here.
  • Full RSpec suite passes locally (2913 examples; 2940 with gemfiles/grape_entity.gemfile).
  • RuboCop clean.
  • CI green.

🤖 Generated with Claude Code

@ericproulx
ericproulx force-pushed the fix/failure-entity-string-message branch from 022b272 to 872d6ef Compare September 18, 2026 09:37
@github-actions

github-actions Bot commented Sep 18, 2026

Copy link
Copy Markdown

Danger Report

No issues found.

View run

@ericproulx
ericproulx force-pushed the fix/failure-entity-string-message branch 2 times, most recently from b2e5dec to 0e224d4 Compare September 18, 2026 12:52
@ericproulx
ericproulx requested a review from dblock September 18, 2026 12:57
…ntity

ErrorFormatter::Base#present applies the entity a route's failure codes
name for the response status to whatever error! was given. An entity
exposing attributes cannot read any off a String, so error!('Unauthorized',
401) under `failure: [[401, 'Unauthorized', API::Error]]` raised while
rendering, and the failsafe answered 500 in place of the 401.

That has been true of the `failure` block method and the `http_codes:`
keyword for as long as they presented errors. #2949 made the `failure:`
keyword present too -- the spelling grape-swagger's README recommends -- so
on master an API that documents its 401 that way and calls error! with a
String turns every 401 into a 500.

The failure entities document a structured error body, and every README
example hands error! a Hash, so a String message is now left to
#wrap_message, which renders it the way it renders without an entity. A
Hash or an object is presented as before, and `with:` and a class's own
Entity are untouched.

An entity written to take the String itself is no longer handed one;
UPGRADING shows moving it to a Hash message.

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
@ericproulx
ericproulx force-pushed the fix/failure-entity-string-message branch from 0e224d4 to b5f8e16 Compare September 19, 2026 12:01
@ericproulx
ericproulx merged commit b416458 into master Sep 19, 2026
69 checks passed
@ericproulx
ericproulx deleted the fix/failure-entity-string-message branch September 19, 2026 16:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants