Flask Custom Error Pages
By default, Flask shows a plain white page when an error occurs. Custom error pages let you replace these with branded, helpful pages that match your site's design and guide users toward a solution.
Common HTTP Error Codes
| Code | Name | When It Appears |
|---|---|---|
| 400 | Bad Request | Malformed request from browser |
| 403 | Forbidden | User lacks permission to access the page |
| 404 | Not Found | URL does not match any route |
| 405 | Method Not Allowed | Wrong HTTP method for the route |
| 500 | Internal Server Error | Unhandled Python exception in your code |
Registering Error Handlers
Use the @app.errorhandler() decorator to register a function for a specific error code. Flask calls this function whenever that error occurs, and the function returns the custom error page.
from flask import Flask, render_template
app = Flask(__name__)
@app.errorhandler(404)
def page_not_found(error):
return render_template('errors/404.html'), 404
@app.errorhandler(500)
def server_error(error):
return render_template('errors/500.html'), 500
@app.errorhandler(403)
def forbidden(error):
return render_template('errors/403.html'), 403The function receives the error object as an argument. Always return the correct HTTP status code as the second return value — without it, Flask sends 200 OK even for error pages.
Creating the Error Templates
Create templates/errors/404.html:
{% extends 'base.html' %}
{% block title %}Page Not Found{% endblock %}
{% block content %}
<h1>404 — Page Not Found</h1>
<p>The page you're looking for doesn't exist or has been moved.</p>
<a href="{{ url_for('home') }}">Go back to the home page</a>
{% endblock %}Create templates/errors/500.html:
{% extends 'base.html' %}
{% block title %}Server Error{% endblock %}
{% block content %}
<h1>500 — Something Went Wrong</h1>
<p>We're working to fix this. Please try again in a few minutes.</p>
<a href="{{ url_for('home') }}">Return home</a>
{% endblock %}How Flask Error Handling Works
Request arrives → Flask tries to match a route
│
Route matched? → NO → @app.errorhandler(404) runs
│
Route matched → View function runs
│
Exception raised? → YES → @app.errorhandler(500) runs
│
Everything OK → Normal response sent
Raising Errors Manually
Your own code can trigger error responses using Flask's abort() function. This immediately stops the current request and triggers the appropriate error handler.
from flask import abort
@app.route('/admin')
def admin_panel():
user_is_admin = False # check real permission here
if not user_is_admin:
abort(403) # triggers the 403 error handler
return '<h1>Admin Panel</h1>'
User visits /admin
│
user_is_admin = False
│
abort(403) called
│
Flask triggers: @app.errorhandler(403)
│
User sees: custom 403 Forbidden page
Using abort() with a Custom Message
Pass a description string to abort() by raising an HTTPException directly:
from werkzeug.exceptions import NotFound
raise NotFound(description='The user ID you requested does not exist.')The error object passed to the handler contains this description in error.description:
@app.errorhandler(404)
def page_not_found(error):
return render_template('errors/404.html', message=error.description), 404Catching All HTTP Errors
Register a handler for all HTTP exceptions at once using HTTPException:
from werkzeug.exceptions import HTTPException
@app.errorhandler(HTTPException)
def handle_http_error(error):
return render_template(
'errors/generic.html',
code=error.code,
name=error.name,
description=error.description
), error.codeSummary
Custom error pages replace Flask's default white error screens with on-brand, helpful pages. Register handlers with @app.errorhandler(code) and render a template with the correct status code as the second return value. Use abort(code) inside view functions to trigger error handlers for permission or logic errors. Always extend your base template so error pages look consistent with the rest of your site.
