44

Can error_handler be set for a blueprint?

@blueprint.errorhandler(404)
def page_not_found(error):
    return 'This page does not exist', 404

edit:

https://github.com/mitsuhiko/flask/blob/18413ed1bf08261acf6d40f8ba65a98ae586bb29/flask/blueprints.py

you can specify an app wide and a blueprint local error_handler

blueblank
  • 4,724
  • 9
  • 48
  • 73
  • The errorhandler() on a blueprint doesn't work reliably. Sometimes it doesn't get used. Makes implementing SPA with client side routing rather annoying. – Shannon Jul 26 '22 at 23:45

7 Answers7

48

You can use Blueprint.app_errorhandler method like this:

bp = Blueprint('errors', __name__)

@bp.app_errorhandler(404)
def handle_404(err):
    return render_template('404.html'), 404

@bp.app_errorhandler(500)
def handle_500(err):
    return render_template('500.html'), 500
suzanshakya
  • 3,524
  • 1
  • 26
  • 22
  • 7
    Even with this in place, `abort(404)` in the blueprint's views would be handled by app's error handler and not this. See [Flask doc](http://flask.pocoo.org/docs/0.10/api/#flask.Blueprint.errorhandler) for it for more info. – Devi May 07 '15 at 06:58
  • Can someone edit/comment on how you would call this app_errorhandler from another blueprint? Is there a flask.redirect() that I need to use? I get this `Could not build url for endpoint 'BaseBP.ErrorHandler'` – Matt Jun 06 '23 at 18:26
22

errorhandler is a method inherited from Flask, not Blueprint. If you are using Blueprint, the equivalent is app_errorhandler.

The documentation suggests the following approach:

def app_errorhandler(self, code):
        """Like :meth:`Flask.errorhandler` but for a blueprint.  This
        handler is used for all requests, even if outside of the blueprint.
        """

Therefore, this should work:

from flask import Blueprint, render_template

USER = Blueprint('user', __name__)

@USER.app_errorhandler(404)
def page_not_found(e):
    """ Return error 404 """
    return render_template('404.html'), 404

On the other hand, while the approach below did not raise any error for me, it didn't work:

from flask import Blueprint, render_template

USER = Blueprint('user', __name__)

@USER.errorhandler(404)
def page_not_found(e):
    """ Return error 404 """
    return render_template('404.html'), 404
marcelovca90
  • 2,673
  • 3
  • 27
  • 34
T. Goncalves
  • 331
  • 2
  • 6
3

add error handling at application level using the request proxy object:

from flask import request,jsonify

@app.errorhandler(404)
@app.errorhandler(405)
def _handle_api_error(ex):
if request.path.startswith('/api/'):
    return jsonify(ex)
else:
    return ex

flask Documentation

vidstige
  • 12,492
  • 9
  • 66
  • 110
swarup260
  • 116
  • 1
  • 5
2

I too couldn't get the top rated answer to work, but here's a workaround.

You can use a catch-all at the end of your Blueprint, not sure how robust/recommended it is, but it does work. You could also add different error messages for different methods too.

@blueprint.route('/<path:path>')
def page_not_found(path):
    return "Custom failure message"
Jonathan Deakin
  • 100
  • 2
  • 6
1

Surprised others didn't mention miguelgrinberg's excellent tutorial.

https://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-vii-error-handling

I found the sentry framework for error handling (links below). Seems overly complex. not sure of the threshold where it becomes useful.

https://flask.palletsprojects.com/en/1.1.x/errorhandling/

https://docs.sentry.io/platforms/python/guides/flask/

CodingMatters
  • 1,275
  • 16
  • 26
1

I combined previous excellent answers with the official docs from Flask, section 'Returning API Errors as JSON', in order to provide a more general approach.

Here is a working PoC that you can copy and paste on your registered blueprint API route handler (e.g. app/api/routes.py):

@blueprint.app_errorhandler(HTTPException)
def handle_exception(e):
    """Return JSON instead of HTML for HTTP errors."""
    # start with the correct headers and status code from the error
    response = e.get_response()
    # replace the body with JSON
    response.data = json.dumps({
        "code": e.code,
        "name": e.name,
        "description": e.description,
    })
    response.content_type = "application/json"
    return response
slightlynybbled
  • 2,408
  • 2
  • 20
  • 38
godzillante
  • 1,174
  • 1
  • 17
  • 32
-10

Flask doesnt support blueprint level error handlers for 404 and 500 errors. A BluePrint is a leaky abstraction. Its better to use a new WSGI App for this, if you need separate error handlers, this makes more sense.

Also i would recommend not to use flask, it uses globals all over the places, which makes your code difficult to manage if it grows bigger.

Nickolay
  • 31,095
  • 13
  • 107
  • 185
TjerkW
  • 2,086
  • 21
  • 26
  • 11
    downvoted, because flask recommendation is highly subjective and has nothing to do with the question asked – iScrE4m Sep 14 '17 at 15:57