Flask Error Handling & Logging

🎯 Custom error handlers

@app.errorhandler(404)
def not_found(error):
    return render_template("errors/404.html"), 404
 
@app.errorhandler(500)
def internal_error(error):
    db.session.rollback()   # clean up any broken transaction
    return render_template("errors/500.html"), 500

🎨 JSON errors (for an API)

@app.errorhandler(404)
def not_found(error):
    if request.path.startswith("/api/"):
        return jsonify({"error": "Not found"}), 404
    return render_template("errors/404.html"), 404

🎯 Custom exception β†’ handler

class InsufficientFundsError(Exception):
    def __init__(self, message):
        self.message = message
 
@app.errorhandler(InsufficientFundsError)
def handle_funds_error(error):
    return jsonify({"error": error.message}), 400
 
# anywhere in app code:
raise InsufficientFundsError("Not enough funds")

↩️ abort() with a message

abort(400, description="'email' is required")
 
@app.errorhandler(400)
def bad_request(error):
    return jsonify({"error": error.description}), 400

πŸ“ Logging

app.logger.debug("...")
app.logger.info("...")
app.logger.warning("...")
app.logger.error("...")
app.logger.critical("...")
app.logger.exception("msg")   # inside except block β€” auto-includes full traceback

File logging w/ rotation

import logging
from logging.handlers import RotatingFileHandler
 
if not app.debug:
    handler = RotatingFileHandler("app.log", maxBytes=10240, backupCount=5)
    handler.setLevel(logging.INFO)
    handler.setFormatter(logging.Formatter(
        "%(asctime)s %(levelname)s: %(message)s [in %(pathname)s:%(lineno)d]"
    ))
    app.logger.addHandler(handler)
    app.logger.setLevel(logging.INFO)

🚨 Catch-all handler

@app.errorhandler(Exception)
def handle_unexpected(error):
    app.logger.exception("Unhandled exception")
    return jsonify({"error": "An unexpected error occurred"}), 500

Never leak raw exception details to the user. Log full detail server-side, return generic message.

πŸ”— Next

Flask Testing & Deployment