Corner Cases of Error Handling in Flask

DONG Yuxuan @ Apr 12, 2019 Asia/Shanghai

Discuss some common questions about how Flask handles errors.

The error handling in Flask is through the error handler which is a normal view function that returns a response, but instead of being registered for a route, it is registered for an exception or HTTP status code that would be raised while trying to handle a request. Official examples are the following:

def handle_bad_request(e):
	return 'bad request!', 400

# or, without the decorator
app.register_error_handler(400, handle_bad_request)

class InsufficientStorage(werkzeug.exceptions.HTTPException):
	code = 507
	description = 'Not enough storage space.'

app.register_error_handler(InsuffcientStorage, handle_507)

raise InsufficientStorage()

Questions below will naturally be asked about the mechanism:

  1. The exception and the HTTP status code, which has the higher priority?

  2. What will happen if some handlers are registered to classes belong to the same class hierarchy?

  3. What will happen if the view function returns a response with error HTTP status code instead of raising an exception?

  4. What will happen if the handler itself raises an exception?

The first two questions are answered by the document quoted below.

When an exception is caught by Flask while handling a request, it is first looked up by code. If no handler is registered for the code, it is looked up by its class hierarchy; the most specific handler is chosen. If no handler is registered, HTTPException subclasses show a generic message about their code, while other exceptions are converted to a generic 500 Internal Server Error.

The answer to the 3rd question is, Flask dosen’t think that a response with an error HTTP status code is an error and the reponse is directly sent to the client instead of being handled by the error handling mechanism.

The last question is the most interesting one. The answer is, if the exception is raised in a non-500 error handler, Flask will invoke the 500-error handler to catch it; if the exception is raised in the 500-error handler, Flask will send the default 500-error page. It implies that if your 400-error handler and 500-error handler both have bugs and the request raised a 400 error, the default 500-error page will be sent.