diff --git a/CHANGELOG.md b/CHANGELOG.md index fdc7d3a3e..26c09ee01 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ * [#2918](https://github.com/ruby-grape/grape/pull/2918): Skip the dry-types round trip when a value already is the declared type - [@ericproulx](https://github.com/ericproulx). * [#2917](https://github.com/ruby-grape/grape/pull/2917): Read path captures out of the router's union match instead of re-running the route's pattern - [@ericproulx](https://github.com/ericproulx). * [#2921](https://github.com/ruby-grape/grape/pull/2921): Pin the router's request-time isolation regressions through requests instead of its instance variables - [@ericproulx](https://github.com/ericproulx). +* [#2931](https://github.com/ruby-grape/grape/pull/2931): Stop building a backtrace in the default `rescue_from` handler unless the API asked for one - [@ericproulx](https://github.com/ericproulx). * Your contribution here. ### 4.0.0 (2026-09-07) diff --git a/lib/grape/middleware/error.rb b/lib/grape/middleware/error.rb index a2dd7c48a..7e5b0bd53 100644 --- a/lib/grape/middleware/error.rb +++ b/lib/grape/middleware/error.rb @@ -192,11 +192,13 @@ def failsafe_payload(headers) ) end + # No +backtrace:+: #resolved_backtrace reads it off +original_exception+ + # when the API asked for one, and only then, since building it is the + # dearest part of rendering the error. def default_rescue_handler(exception) error_response( Grape::Exceptions::ErrorResponse.new( message: exception.message, - backtrace: exception.backtrace, original_exception: exception ) )