#2103·sinatra

catch-all error handler does not ever run in dev despite `set :show_exceptions, :after_handler`

Author: davetron5000Created May 4, 2025Updated May 4, 2025

The docs say this:

The error handler is invoked any time an exception is raised from a route block or a filter. But note in development it will only run if you set the show exceptions option to :after_handler:

set :show_exceptions, :after_handler

A catch-all error handler can be defined with error and a block:

error do 'Sorry there was a nasty error' end

This leads me to believe that in dev, error do—the catch-all—will be called. However, that is not the case.

Of note, the catch-all is also not called if the underlying error is a bad request or not found.

This is due to this code:

https://github.com/sinatra/sinatra/blob/91cfb548c9e50a65324a9ce9e4ea5f10cd897027/lib/sinatra/base.rb#L1235-L1252

In the case where no configured handler matches, we'd proceed to line 1239 where not found and bad request are checked. If either of those is true, hard-coded behavior happens and the catch-all is not called.

If it's not a bad request or not found, execution proceeds to line 1250. Since :show_exceptions is set to :after_handler, which is truthy, the caught exception is re-raised and the catch-all is not called.

Also of note, you cannot avoid this behavior via error Exception do. error StandardError do works for anything inheriting StandardError, but that is not a true catch-all.

Proposed Solutions

  • Simplest thing is to document that the catch-all does not catch all and that to actually catch-all you must do error Exception do...
  • Other option would be to re-write this code so that the catch all does catch-all, however this may be considered a break change if anyone is relying on the current behavior