BetterErrors / better_errors

Better error page for Rack apps
MIT License
6.88k stars 437 forks source link

Show real cause of ActionView::Template::Error with Rails 6 #477

Closed RobinDaugherty closed 4 years ago

RobinDaugherty commented 4 years ago

In #459 we stopped always showing the cause of an exception. This backs that out a bit by adding a special case for ActionView::Template::Error provided by Rails 6. This should solve the incorrect backtrace in that case.

Here's how this came to be:

  1. v0.0.1 of Better Errors has a special case for ActionView::Template::Error to display its #original_exception instead of the top-level error.
  2. v0.0.2 changes that to follow any original_exception regardless of the exception class. I'm not sure why this was done, but likely it's because there are errors similar to ActionView::Template::Error that it's desirable for.
  3. Ruby 2.1.0 adds Exception#cause which provides a standard pattern for the thing that Rails was doing with #original_exception.
  4. 325 changes Better Errors to treat #cause just like it had for errors that had an #original_exception.

  5. Over time, many bug reports come in from projects where Better Errors is showing the wrong exception. _This is because Better Errors always follows a #cause now, where before it would follow #original_exception only when Rails provided one, and Ruby exceptions frequently have a #cause but the top-level error is the informative one._
  6. In #459 I remove the collapsing to Exception#cause completely, but leave the older Rails #original_exception behavior in place.
  7. New issues appear where in Rails 6, the backtrace doesn't have a frame where the template can be inspected. _This is because in Rails 6, they stopped providing #original_exception and instead started providing #cause, following the Ruby standard._
  8. In #463 I added a special case for the ActionView::Template::Error, prepending a stack trace frame to the top-level exception so there's something to work with.
  9. New issues such as #470 are opened where when the exception occurred inside of the template execution, but not in the template itself, the backtrace is useless. (I had foreseen this and opened #466.) This is because the ActionView::Template::Error instance only refers to the line in the template that was being executed when the exception was raised.

So this change adds back the original, original behavior of treating ActionView::Template::Error as a special case, stripping off the top-level exception and showing its #cause. There might be other Rails errors that need to be treated this way. If you identify one please let us know!

The behavior to support all old Rails exceptions, where it always follows the #original_exception is still there.

Fixes #466. Fixes #470.