35

Flask has a good error handler by using abort() or when the error truly occurred.

From Flask documentation there is an example for error 404 handler:

@app.errorhandler(404)
def not_found(error):
    return render_template('404.html'), 404

So, I tried to create custom error code like

if False:
    abort(777)

@app.errorhandler(777)
def something_is_wrong(error):
    return render_template('777.html'), 777

But it does not work and the Werkzeug debugger says: LookupError: no exception for 777

I found this question which says I should do it like this:

if False:
    return '777 error', 777

Unfortunately, the code above produce white-screen, even the Werkzeug debugger does not come out

I know I can simply do:

if False:
    return render_template('777.html')

But it will make the code cleaner if I use the abort(). Is there any way to create custom error code?

Community
  • 1
  • 1
hrsetyono
  • 4,474
  • 13
  • 46
  • 80
  • If you're using Flask 1.0, it seems that the approach has changed and you can raise and catch custom exceptions: http://flask.pocoo.org/docs/1.0/patterns/apierrors/ – Tom Saleeba May 02 '19 at 12:09

4 Answers4

50

The list of possible HTTP status codes is fixed by the Internet Assigned Numbers Authority, so you cannot add a custom one. Werkzeug recognizes this and tries to stop you sending a meaningless code to the browser. Look through the list of status codes to find one that matches your error and use that one.

Edit: Adding status codes to Werkzeug/Flask

import werkzeug.exceptions as ex
from flask import Flask, abort

class PaymentRequired(ex.HTTPException):
    code = 402
    description = '<p>You will pay for this!</p>'

abort.mappings[402] = PaymentRequired

app = Flask(__name__)

@app.route('/')
def mainpage():
    abort(402)

@app.errorhandler(402)
def payme(e):
    return 'Pay me!'

app.run()
Abe Karplus
  • 8,350
  • 2
  • 27
  • 24
  • Thanks, I use error 400 bad_request for when the user manually typed wrong value in the URL (because the URL contains user input from dropdown list). **It works, but is it the correct one?** – hrsetyono Sep 05 '12 at 16:49
  • 1
    Probably, depends on why you're refusing the input. Another appropriate / common code could be 404, or maybe even 403 if you're blocking for security reason. – Thomas Orozco Sep 05 '12 at 16:59
  • 4
    What about 402? That one is undefined in werkzeug but it should be a valid one. – Pwnna Feb 26 '13 at 06:34
  • @ultimatebuster It's undefined because, as the list states, it is reserved for future use. I doubt that "Payment Required" is an accurate description of your error, so would advise against 402. Just do `return something_is_wrong()` instead of `abort(777)`. It's clean and not against the standard. – Abe Karplus Feb 26 '13 at 06:59
  • Actually that's exactly what I want to say. I want to say: payment is required for this service. – Pwnna Feb 26 '13 at 14:02
  • Oh, sorry. I'll look into the Werkzeug source to see how a new error code could be added. – Abe Karplus Feb 26 '13 at 18:22
  • I need to send back `504` (gateway timeout) but Flask doesn't seem to support that either. Any idea why? – Ben Feb 26 '13 at 18:42
  • 6
    `abort.mappings` no longer seems to exist; use this instead: `exceptions.default_exceptions[402] = PaymentRequired` – claymation Dec 10 '14 at 18:48
  • 1
    In my case (Flask==0.11.1, Werkzeug==0.11.10) it abort.mapping[402] = PaymentRequired, not "mappings" – Stan Zeez Jul 12 '16 at 12:34
  • in Flask 0.11.1, `abort.mapping` instead of `abort.mappings`,and you don't need change `abort.mapping`, `abort.mapping` is `default_exceptions`, you can `from werkzeug.exceptions import default_exceptions`. – xavierskip Jul 28 '16 at 13:37
  • Well technically you *can* use a custom code, but your client might not understand it. The Twitter API does that with "420" for example, which is not an official code. – bfontaine Dec 28 '16 at 20:59
18

Depending on the reading of the question this might come in handy.

There is an easier way to add customer error page handling for a specific exception, you can do this:

class MyCustom404(Exception):
    pass

@app.errorhandler(404)
def page_not_found(error):
    return render_template("errors/404.html"), 404

@app.errorhandler(MyCustom404)
def special_page_not_found(error):
    return render_template("errors/custom_404.html"), 404

...then trigger your new handler when you need it with

raise MyCustom404

See the docs here.

Andrew Barrett
  • 19,721
  • 4
  • 47
  • 52
10

In my case, Flask==0.11.1 Werkzeug==0.11.10

I use abort the http status code 451 for example.

if you want use abort() with a code,a int number,like abort(451), at first you should create a custom HTTPException, a subclass of HTTPException.and append your HTTPException to default_exceptions.

from werkzeug.exceptions import HTTPException, default_exceptions,  Aborter
class UnavailableForLegalReasons(HTTPException):
    code = 451
    description = 'BIG BROTHER IS WATCHING YOU'

default_exceptions[451] = UnavailableForLegalReasons
abort = Aborter()  # don't from flask import abort

@app.errorhandler(451)
def uflr(e):
    return e, 451

@app.route('/debug')
def debug():
    abort(451)

then when you access the path in browser, you can look this enter image description here

but the http reason phrase is UNKNOWN,

you can change it

from werkzeug.http import HTTP_STATUS_CODES
HTTP_STATUS_CODES[451] = 'Unavailable For Legal Reasons'  # or even empty

enter image description here

xavierskip
  • 431
  • 4
  • 12
0

You could also use Flask API and its error handling system:

http://www.flaskapi.org/api-guide/exceptions/

Mathieu Rodic
  • 6,637
  • 2
  • 43
  • 49