Flask Error Handling: 404, 500 Errors and Custom Responses

In web development, encountering non-existent pages or server internal errors is common. Returning the system’s default error pages (such as “404 Not Found” or “500 Internal Server Error”) directly not only results in a poor user experience but may also confuse users. Flask provides a flexible error handling mechanism that allows us to customize these error responses, making error messages more user-friendly and aligned with project requirements.

Default Error Responses in Flask

Let’s first examine Flask’s default error behavior with a basic application:

from flask import Flask

app = Flask(__name__)

@app.route('/')
def home():
    return "Welcome to the homepage"

if __name__ == '__main__':
    app.run(debug=True)  # Run in debug mode

When running this app, accessing these scenarios will trigger default errors:
1. Accessing a non-existent URL (e.g., http://localhost:5000/abc): Flask returns a plain “404 Not Found” page:

   404 Not Found
   The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.
  1. Intentionally causing a code error (e.g., adding 1/0 division-by-zero in a view function): Flask returns “500 Internal Server Error” with detailed error stacks (in debug mode), which ordinary users cannot understand.

While default error pages are simple, they are insufficiently user-friendly for most projects. Thus, customizing these responses is necessary.

Custom Error Responses with @app.errorhandler

Flask uses the @app.errorhandler decorator to define custom logic for specific error codes (e.g., 404, 500). The decorator takes an error code as an argument, and the function returns custom content (HTML, JSON, etc.).

1. Custom 404 Error Page

For non-existent pages, return a friendly message like “The page has flown away~” with a link to the homepage. Example code:

from flask import Flask

app = Flask(__name__)

@app.route('/')
def home():
    return "Welcome to the homepage"

# Handle 404 errors
@app.errorhandler(404)
def page_not_found(error):
    # Return custom HTML with a 404 status code
    return '''
    <!DOCTYPE html>
    <html>
    <head>
        <title>Page Not Found</title>
        <style>
            body { text-align: center; margin-top: 50px; font-family: sans-serif; }
            h1 { color: #ff6b6b; }
            a { color: #4ecdc4; text-decoration: none; }
        </style>
    </head>
    <body>
        <h1>Oops, the page is missing!</h1>
        <p>The page you're looking for might have been "borrowed" by aliens or you entered the URL incorrectly.</p>
        <a href="/">Return to homepage</a>
    </body>
    </html>
    ''', 404  # Explicitly return 404 status code

if __name__ == '__main__':
    app.run(debug=False)  # Disable debug in production to avoid detailed error pages

Visiting http://localhost:5000/abc will display the custom 404 page.

2. Custom 500 Error Page

For server internal errors (e.g., code exceptions), return a “Server is on a coffee break” message. Example:

from flask import Flask

app = Flask(__name__)

@app.route('/')
def home():
    return "Welcome to the homepage"

@app.route('/error')
def cause_error():
    return 1 / 0  # Trigger 500 error (division by zero)

# Handle 500 errors
@app.errorhandler(500)
def server_error(error):
    return '''
    <!DOCTYPE html>
    <html>
    <head>
        <title>Server Error</title>
        <style>
            body { text-align: center; margin-top: 50px; font-family: sans-serif; }
            h1 { color: #ffc857; }
            p { color: #6a6a6a; }
            a { color: #4ecdc4; text-decoration: none; }
        </style>
    </head>
    <body>
        <h1>Server is on a coffee break~</h1>
        <p>Sorry, the system encountered an issue while processing your request. Please try again later!</p>
        <a href="/">Return to homepage</a>
    </body>
    </html>
    ''', 500

if __name__ == '__main__':
    app.run(debug=False)

Visiting http://localhost:5000/error will show the custom 500 page.

3. Returning JSON Error Responses

For API projects, return JSON-formatted error messages. Use jsonify for this:

from flask import Flask, jsonify

app = Flask(__name__)

@app.route('/api/user/<int:user_id>')
def get_user(user_id):
    if user_id not in [1, 2, 3]:
        # Return 404 JSON error
        return jsonify({
            "status": "error",
            "code": 404,
            "message": "User not found"
        }), 404
    return jsonify({"id": user_id, "name": "User"})

if __name__ == '__main__':
    app.run(debug=False)

Accessing a non-existent user ID (e.g., /api/user/99) returns:

{
  "status": "error",
  "code": 404,
  "message": "User not found"
}

Summary

Flask’s error handling centers on the @app.errorhandler decorator, which defines custom responses for specific error codes (404, 500, etc.). Custom error pages enhance user experience by avoiding confusing default messages. For simple cases, return HTML strings directly; for complex projects, use templates, JSON, or error logging for debugging.

With these methods, you can easily make Flask applications’ error handling more user-friendly and controllable.

Xiaoye