Using "rescue_from Exception" to render a 500 page with the application layout will not catch all Exceptions

I’m not really sure whether this is a doc bug or a regular bug, so I figured I would open a thread here to figure out which.

If you use rescue_from Exception to render a dynamic 500 page with your application layout, and the exception was triggered from the application layout to begin with, it will escape the dynamic error page and render the one in public. Granted, this sounds obvious, but the documentation for rescue_from states that “Exceptions raised inside exception handlers are not propagated up,” when in this situation that’s clearly not the case.

I have a reproduction of this issue here: https://github.com/timraymond/rails-issue-rescue-from and a Docker image of it, if that’s your cup of tea: Docker Hub (docker pull timraymond/rails-issue). If you visit the “/explode” path, the exception raised there will be successfully caught by the dynamic 500 page. If you visit the “/greet/:name” path, it will escape the dynamic 500 page because of the exception raised in the application layout. The conditional in the layout is contrived, but is intended to represent complex logic that can trigger an exception in the layout when rendering some actions but not others.

I see in the edge guides that there’s also a way to get this functionality by creating a route for “/500”. I’m not sure if this would be similarly affected if an exception was raised by a layout, but it’s something to consider as well, and perhaps someone who is more familiar with that feature can chime in :slight_smile:

Let me know if I should open this up on GitHub as an issue, or if docrails needs to be updated to reflect that some exceptions can escape.

I don’t know if rescue_from Exception should catch everything as you expect, what I do know is that you can use the router to point to a normal controller / action(s) and use any layout you want for that.

Check this post at Plataformatec’s blog: http://blog.plataformatec.com.br/2012/01/my-five-favorite-hidden-features-in-rails-3-2/, it details a bit how the feature works.

If you want to dynamically generate error pages, use rambulance gem. It’s quite easy to use. You don’t have to know about how it works. It just works out of the box. Although, you might still have the same issue on the layout.

rescue_from Exception is evil. NEVER do it. Even config.exceptions_app = self.routes is a horrible idea, as it have some problems like:

  • ErrorsController doesn’t always have all the necessary methods(e.g. bad_request, conflict)
  • And if the router has get ‘/*username’, it’ll probably raise an exception or display 404 page unexpectedly. I believe it should be removed from the edgeguides. We should stop doing both rescue_from Exception and config.exceptions_app = self.routes.

If this is something almost all people want, Rails should provide an exceptions app that dynamically generates an error page, I believe it’s an application-level concern, though.