<h1>Handling Application Errors<aclass="headerlink"href="#handling-application-errors"title="Link to this heading">¶</a></h1>
<p>Applications fail, servers fail. Sooner or later you will see an exception
in production. Even if your code is 100% correct, you will still see
exceptions from time to time. Why? Because everything else involved will
fail. Here are some situations where perfectly fine code can lead to server
errors:</p>
<ulclass="simple">
<li><p>the client terminated the request early and the application was still
reading from the incoming data</p></li>
<li><p>the database server was overloaded and could not handle the query</p></li>
<li><p>a filesystem is full</p></li>
<li><p>a harddrive crashed</p></li>
<li><p>a backend server overloaded</p></li>
<li><p>a programming error in a library you are using</p></li>
<li><p>network connection of the server to another system failed</p></li>
</ul>
<p>And that’s just a small sample of issues you could be facing. So how do we
deal with that sort of problem? By default if your application runs in
production mode, and an exception is raised Flask will display a very simple
page for you and log the exception to the <aclass="reference internal"href="api.html#flask.Flask.logger"title="flask.Flask.logger"><codeclass="xref py py-attr docutils literal notranslate"><spanclass="pre">logger</span></code></a>.</p>
<p>But there is more you can do, and we will cover some better setups to deal
with errors including custom exceptions and 3rd party tools.</p>
<sectionid="error-logging-tools">
<spanid="id1"></span><h2>Error Logging Tools<aclass="headerlink"href="#error-logging-tools"title="Link to this heading">¶</a></h2>
<p>Sending error mails, even if just for critical ones, can become
overwhelming if enough users are hitting the error and log files are
typically never looked at. This is why we recommend using <aclass="reference external"href="https://sentry.io/">Sentry</a> for dealing with application errors. It’s
available as a source-available project <aclass="reference external"href="https://github.com/getsentry/sentry">on GitHub</a> and is also available as a <aclass="reference external"href="https://sentry.io/signup/">hosted version</a> which you can try for free. Sentry
aggregates duplicate errors, captures the full stack trace and local
variables for debugging, and sends you mails based on new errors or
frequency thresholds.</p>
<p>To use Sentry you need to install the <codeclass="docutils literal notranslate"><spanclass="pre">sentry-sdk</span></code> client with extra
<li><p>Sentry also supports catching errors from a worker queue
(RQ, Celery, etc.) in a similar fashion. See the <aclass="reference external"href="https://docs.sentry.io/platforms/python/">Python SDK docs</a> for more information.</p></li>
<h2>Error Handlers<aclass="headerlink"href="#error-handlers"title="Link to this heading">¶</a></h2>
<p>When an error occurs in Flask, an appropriate <aclass="reference external"href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status">HTTP status code</a> will be
returned. 400-499 indicate errors with the client’s request data, or
about the data requested. 500-599 indicate errors with the server or
application itself.</p>
<p>You might want to show custom error pages to the user when an error occurs.
This can be done by registering error handlers.</p>
<p>An error handler is a function that returns a response when a type of error is
raised, similar to how a view is a function that returns a response when a
request URL is matched. It is passed the instance of the error being handled,
which is most likely a <aclass="reference external"href="https://werkzeug.palletsprojects.com/en/stable/exceptions/#werkzeug.exceptions.HTTPException"title="(in Werkzeug v3.1.x)"><codeclass="xref py py-exc docutils literal notranslate"><spanclass="pre">HTTPException</span></code></a>.</p>
<p>The status code of the response will not be set to the handler’s code. Make
sure to provide the appropriate HTTP status code when returning a response from
a handler.</p>
<sectionid="registering">
<h3>Registering<aclass="headerlink"href="#registering"title="Link to this heading">¶</a></h3>
<p>Register handlers by decorating a function with
<aclass="reference internal"href="api.html#flask.Flask.errorhandler"title="flask.Flask.errorhandler"><codeclass="xref py py-meth docutils literal notranslate"><spanclass="pre">errorhandler()</span></code></a>. Or use
<aclass="reference internal"href="api.html#flask.Flask.register_error_handler"title="flask.Flask.register_error_handler"><codeclass="xref py py-meth docutils literal notranslate"><spanclass="pre">register_error_handler()</span></code></a> to register the function later.
Remember to set the error code when returning the response.</p>
<aclass="reference external"href="https://werkzeug.palletsprojects.com/en/stable/exceptions/#werkzeug.exceptions.BadRequest"title="(in Werkzeug v3.1.x)"><codeclass="xref py py-exc docutils literal notranslate"><spanclass="pre">BadRequest</span></code></a> and their HTTP codes are interchangeable
when registering handlers. (<codeclass="docutils literal notranslate"><spanclass="pre">BadRequest.code</span><spanclass="pre">==</span><spanclass="pre">400</span></code>)</p>
<p>Non-standard HTTP codes cannot be registered by code because they are not known
by Werkzeug. Instead, define a subclass of
<aclass="reference external"href="https://werkzeug.palletsprojects.com/en/stable/exceptions/#werkzeug.exceptions.HTTPException"title="(in Werkzeug v3.1.x)"><codeclass="xref py py-class docutils literal notranslate"><spanclass="pre">HTTPException</span></code></a> with the appropriate code and
<p>Handlers can be registered for any exception class, not just
<aclass="reference external"href="https://werkzeug.palletsprojects.com/en/stable/exceptions/#werkzeug.exceptions.HTTPException"title="(in Werkzeug v3.1.x)"><codeclass="xref py py-exc docutils literal notranslate"><spanclass="pre">HTTPException</span></code></a> subclasses or HTTP status
codes. Handlers can be registered for a specific class, or for all subclasses
of a parent class.</p>
</section>
<sectionid="handling">
<h3>Handling<aclass="headerlink"href="#handling"title="Link to this heading">¶</a></h3>
<p>When building a Flask application you <em>will</em> run into exceptions. If some part
of your code breaks while handling a request (and you have no error handlers
registered), a “500 Internal Server Error”
(<aclass="reference external"href="https://werkzeug.palletsprojects.com/en/stable/exceptions/#werkzeug.exceptions.InternalServerError"title="(in Werkzeug v3.1.x)"><codeclass="xref py py-exc docutils literal notranslate"><spanclass="pre">InternalServerError</span></code></a>) will be returned by default.
Similarly, “404 Not Found”
(<aclass="reference external"href="https://werkzeug.palletsprojects.com/en/stable/exceptions/#werkzeug.exceptions.NotFound"title="(in Werkzeug v3.1.x)"><codeclass="xref py py-exc docutils literal notranslate"><spanclass="pre">NotFound</span></code></a>) error will occur if a request is sent to an unregistered route.
If a route receives an unallowed request method, a “405 Method Not Allowed”
(<aclass="reference external"href="https://werkzeug.palletsprojects.com/en/stable/exceptions/#werkzeug.exceptions.MethodNotAllowed"title="(in Werkzeug v3.1.x)"><codeclass="xref py py-exc docutils literal notranslate"><spanclass="pre">MethodNotAllowed</span></code></a>) will be raised. These are all
subclasses of <aclass="reference external"href="https://werkzeug.palletsprojects.com/en/stable/exceptions/#werkzeug.exceptions.HTTPException"title="(in Werkzeug v3.1.x)"><codeclass="xref py py-class docutils literal notranslate"><spanclass="pre">HTTPException</span></code></a> and are provided by
default in Flask.</p>
<p>Flask gives you the ability to raise any HTTP exception registered by
Werkzeug. However, the default HTTP exceptions return simple exception
pages. You might want to show custom error pages to the user when an error occurs.
This can be done by registering error handlers.</p>
<p>When Flask catches an exception while handling a request, it is first looked up by code.
If no handler is registered for the code, Flask looks up the error by its class hierarchy; the most specific handler is chosen.
If no handler is registered, <aclass="reference external"href="https://werkzeug.palletsprojects.com/en/stable/exceptions/#werkzeug.exceptions.HTTPException"title="(in Werkzeug v3.1.x)"><codeclass="xref py py-class docutils literal notranslate"><spanclass="pre">HTTPException</span></code></a> subclasses show a
generic message about their code, while other exceptions are converted to a
generic “500 Internal Server Error”.</p>
<p>For example, if an instance of <aclass="reference external"href="https://docs.python.org/3/library/exceptions.html#ConnectionRefusedError"title="(in Python v3.13)"><codeclass="xref py py-exc docutils literal notranslate"><spanclass="pre">ConnectionRefusedError</span></code></a> is raised,
and a handler is registered for <aclass="reference external"href="https://docs.python.org/3/library/exceptions.html#ConnectionError"title="(in Python v3.13)"><codeclass="xref py py-exc docutils literal notranslate"><spanclass="pre">ConnectionError</span></code></a> and
<aclass="reference external"href="https://docs.python.org/3/library/exceptions.html#ConnectionRefusedError"title="(in Python v3.13)"><codeclass="xref py py-exc docutils literal notranslate"><spanclass="pre">ConnectionRefusedError</span></code></a>, the more specific <aclass="reference external"href="https://docs.python.org/3/library/exceptions.html#ConnectionRefusedError"title="(in Python v3.13)"><codeclass="xref py py-exc docutils literal notranslate"><spanclass="pre">ConnectionRefusedError</span></code></a>
handler is called with the exception instance to generate the response.</p>
<p>Handlers registered on the blueprint take precedence over those registered
globally on the application, assuming a blueprint is handling the request that
raises the exception. However, the blueprint cannot handle 404 routing errors
because the 404 occurs at the routing level before the blueprint can be
determined.</p>
</section>
<sectionid="generic-exception-handlers">
<h3>Generic Exception Handlers<aclass="headerlink"href="#generic-exception-handlers"title="Link to this heading">¶</a></h3>
<p>It is possible to register error handlers for very generic base classes
such as <codeclass="docutils literal notranslate"><spanclass="pre">HTTPException</span></code> or even <codeclass="docutils literal notranslate"><spanclass="pre">Exception</span></code>. However, be aware that
these will catch more than you might expect.</p>
<p>For example, an error handler for <codeclass="docutils literal notranslate"><spanclass="pre">HTTPException</span></code> might be useful for turning
the default HTML errors pages into JSON. However, this
handler will trigger for things you don’t cause directly, such as 404
and 405 errors during routing. Be sure to craft your handler carefully
so you don’t lose information about the HTTP error.</p>
<p>An error handler for <codeclass="docutils literal notranslate"><spanclass="pre">Exception</span></code> might seem useful for changing how
all errors, even unhandled ones, are presented to the user. However,
this is similar to doing <codeclass="docutils literal notranslate"><spanclass="pre">except</span><spanclass="pre">Exception:</span></code> in Python, it will
capture <em>all</em> otherwise unhandled errors, including all HTTP status
codes.</p>
<p>In most cases it will be safer to register handlers for more
specific exceptions. Since <codeclass="docutils literal notranslate"><spanclass="pre">HTTPException</span></code> instances are valid WSGI
responses, you could also pass them through directly.</p>
<p>Error handlers still respect the exception class hierarchy. If you
register handlers for both <codeclass="docutils literal notranslate"><spanclass="pre">HTTPException</span></code> and <codeclass="docutils literal notranslate"><spanclass="pre">Exception</span></code>, the
<codeclass="docutils literal notranslate"><spanclass="pre">Exception</span></code> handler will not handle <codeclass="docutils literal notranslate"><spanclass="pre">HTTPException</span></code> subclasses
because the <codeclass="docutils literal notranslate"><spanclass="pre">HTTPException</span></code> handler is more specific.</p>
</section>
<sectionid="unhandled-exceptions">
<h3>Unhandled Exceptions<aclass="headerlink"href="#unhandled-exceptions"title="Link to this heading">¶</a></h3>
<p>When there is no error handler registered for an exception, a 500
Internal Server Error will be returned instead. See
<aclass="reference internal"href="api.html#flask.Flask.handle_exception"title="flask.Flask.handle_exception"><codeclass="xref py py-meth docutils literal notranslate"><spanclass="pre">flask.Flask.handle_exception()</span></code></a> for information about this
behavior.</p>
<p>If there is an error handler registered for <codeclass="docutils literal notranslate"><spanclass="pre">InternalServerError</span></code>,
this will be invoked. As of Flask 1.1.0, this error handler will always
be passed an instance of <codeclass="docutils literal notranslate"><spanclass="pre">InternalServerError</span></code>, not the original
unhandled error.</p>
<p>The original error is available as <codeclass="docutils literal notranslate"><spanclass="pre">e.original_exception</span></code>.</p>
<p>An error handler for “500 Internal Server Error” will be passed uncaught
exceptions in addition to explicit 500 errors. In debug mode, a handler
for “500 Internal Server Error” will not be used. Instead, the
<h2>Custom Error Pages<aclass="headerlink"href="#custom-error-pages"title="Link to this heading">¶</a></h2>
<p>Sometimes when building a Flask application, you might want to raise a
<aclass="reference external"href="https://werkzeug.palletsprojects.com/en/stable/exceptions/#werkzeug.exceptions.HTTPException"title="(in Werkzeug v3.1.x)"><codeclass="xref py py-exc docutils literal notranslate"><spanclass="pre">HTTPException</span></code></a> to signal to the user that
something is wrong with the request. Fortunately, Flask comes with a handy
<aclass="reference internal"href="api.html#flask.abort"title="flask.abort"><codeclass="xref py py-func docutils literal notranslate"><spanclass="pre">abort()</span></code></a> function that aborts a request with a HTTP error from
werkzeug as desired. It will also provide a plain black and white error page
for you with a basic description, but nothing fancy.</p>
<p>Depending on the error code it is less or more likely for the user to
actually see such an error.</p>
<p>Consider the code below, we might have a user profile route, and if the user
fails to pass a username we can raise a “400 Bad Request”. If the user passes a
username and we can’t find it, we raise a “404 Not Found”.</p>
<spanclass="cp">{%</span><spanclass="k">block</span><spanclass="nv">title</span><spanclass="cp">%}</span>Page Not Found<spanclass="cp">{%</span><spanclass="k">endblock</span><spanclass="cp">%}</span>
<spanclass="p"><</span><spanclass="nt">h1</span><spanclass="p">></span>Page Not Found<spanclass="p"></</span><spanclass="nt">h1</span><spanclass="p">></span>
<spanclass="p"><</span><spanclass="nt">p</span><spanclass="p">></span>What you were looking for is just not there.
<spanclass="cp">{%</span><spanclass="k">block</span><spanclass="nv">title</span><spanclass="cp">%}</span>Internal Server Error<spanclass="cp">{%</span><spanclass="k">endblock</span><spanclass="cp">%}</span>
<spanclass="p"><</span><spanclass="nt">h1</span><spanclass="p">></span>Internal Server Error<spanclass="p"></</span><spanclass="nt">h1</span><spanclass="p">></span>
<spanclass="p"><</span><spanclass="nt">p</span><spanclass="p">></span>Oops... we seem to have made a mistake, sorry!<spanclass="p"></</span><spanclass="nt">p</span><spanclass="p">></span>
<h2>Blueprint Error Handlers<aclass="headerlink"href="#blueprint-error-handlers"title="Link to this heading">¶</a></h2>
<p>In <aclass="reference internal"href="blueprints.html"><spanclass="doc">Modular Applications with Blueprints</span></a>, most error handlers will work as expected.
However, there is a caveat concerning handlers for 404 and 405
exceptions. These error handlers are only invoked from an appropriate
<codeclass="docutils literal notranslate"><spanclass="pre">raise</span></code> statement or a call to <codeclass="docutils literal notranslate"><spanclass="pre">abort</span></code> in another of the blueprint’s
view functions; they are not invoked by, e.g., an invalid URL access.</p>
<p>This is because the blueprint does not “own” a certain URL space, so
the application instance has no way of knowing which blueprint error
handler it should run if given an invalid URL. If you would like to
execute different handling strategies for these errors based on URL
prefixes, they may be defined at the application level using the
<spanclass="c1"># we return a json saying so</span>
<spanclass="k">return</span><spanclass="n">jsonify</span><spanclass="p">(</span><spanclass="n">message</span><spanclass="o">=</span><spanclass="s2">"Method Not Allowed"</span><spanclass="p">),</span><spanclass="mi">405</span>
<spanclass="k">else</span><spanclass="p">:</span>
<spanclass="c1"># otherwise we return a generic site-wide 405 page</span>
<h2>Returning API Errors as JSON<aclass="headerlink"href="#returning-api-errors-as-json"title="Link to this heading">¶</a></h2>
<p>When building APIs in Flask, some developers realise that the built-in
exceptions are not expressive enough for APIs and that the content type of
<emclass="mimetype">text/html</em> they are emitting is not very useful for API consumers.</p>
<p>Using the same techniques as above and <aclass="reference internal"href="api.html#flask.json.jsonify"title="flask.json.jsonify"><codeclass="xref py py-func docutils literal notranslate"><spanclass="pre">jsonify()</span></code></a> we can return JSON
responses to API errors. <aclass="reference internal"href="api.html#flask.abort"title="flask.abort"><codeclass="xref py py-func docutils literal notranslate"><spanclass="pre">abort()</span></code></a> is called
with a <codeclass="docutils literal notranslate"><spanclass="pre">description</span></code> parameter. The error handler will
use that as the JSON error message, and set the status code to 404.</p>
<spanclass="n">abort</span><spanclass="p">(</span><spanclass="mi">404</span><spanclass="p">,</span><spanclass="n">description</span><spanclass="o">=</span><spanclass="s2">"Resource not found"</span><spanclass="p">)</span>
<spanclass="k">raise</span><spanclass="n">InvalidAPIUsage</span><spanclass="p">(</span><spanclass="s2">"No user id provided!"</span><spanclass="p">)</span>
<spanclass="k">raise</span><spanclass="n">InvalidAPIUsage</span><spanclass="p">(</span><spanclass="s2">"No such user!"</span><spanclass="p">,</span><spanclass="n">status_code</span><spanclass="o">=</span><spanclass="mi">404</span><spanclass="p">)</span>
<p>A view can now raise that exception with an error message. Additionally
some extra payload can be provided as a dictionary through the <codeclass="code docutils literal notranslate"><spanclass="pre">payload</span></code>
parameter.</p>
</section>
<sectionid="logging">
<h2>Logging<aclass="headerlink"href="#logging"title="Link to this heading">¶</a></h2>
<p>See <aclass="reference internal"href="logging.html"><spanclass="doc">Logging</span></a> for information about how to log exceptions, such as
by emailing them to admins.</p>
</section>
<sectionid="debugging">
<h2>Debugging<aclass="headerlink"href="#debugging"title="Link to this heading">¶</a></h2>
<p>See <aclass="reference internal"href="debugging.html"><spanclass="doc">Debugging Application Errors</span></a> for information about how to debug errors in