
Custom Exception Handlers: Global Error Management
Beyond status codes. Learn how to catch domain-specific exceptions and return standardized error formats across your entire API.
Custom Exception Handlers: Global Error Management
Sometimes you don't want to manualy raise HTTPException in every function. If you have a custom Python error (like DatabaseConnectionError), you want your API to automatically know how to handle it globally.
In this lesson, we learn how to map any Python Exception to a clean HTTP response.
1. Defining a Custom Exception
First, we define a standard Python class for our error. This keeps our "Business Logic" clean and independent of FastAPI.
class InsufficientFundsError(Exception):
def __init__(self, amount_missing: int):
self.amount_missing = amount_missing
2. Registering the Handler
We use the @app.exception_handler decorator to tell FastAPI: "Whenever you see this specific error, run this code."
from fastapi import Request
from fastapi.responses import JSONResponse
@app.exception_handler(InsufficientFundsError)
async def funds_exception_handler(request: Request, exc: InsufficientFundsError):
return JSONResponse(
status_code=402,
content={
"error": "low_balance",
"message": f"You are missing {exc.amount_missing} credits.",
}
)
3. Overriding Built-in Handlers
This is a "Pro Tip" for building enterprise APIs. You can even override FastAPI's built-in handlers for validation errors (RequestValidationError) to change how they look.
from fastapi.exceptions import RequestValidationError
@app.exception_handler(RequestValidationError)
async def validation_exception_handler(request, exc):
return JSONResponse(
status_code=422,
content={"custom_error": "Your data is malformed!"}
)
4. Why Use Global Handlers?
- Cleaner Code: Your endpoint logic simply says
account.withdraw(100). If it fails, the global handler takes over. - Consistency: You ensure that every error follows the exact same JSON structure, making it easier for Frontend developers.
- Logs: You can add logging or alerting (like sending a message to Slack) inside the handler without cluttering your main code.
Visualizing Global Handlers
graph TD
A["Endpoint Function"] --> B["Logic: Raise MyCustomError"]
B --> C{Does a Handler exist?}
C -- "Yes" --> D["Run Custom Exception Handler"]
C -- "No" --> E["Standard 500 Internal Error"]
D --> F["Beautiful JSON Response"]
Summary
- Custom Exceptions: Keep your logic focused on the domain, not the web.
exception_handler: Maps Python errors to HTTP responses.JSONResponse: Use it to return manual JSON payloads from your handlers.- Consistency: Global handlers ensure your API "fails well."
In the next lesson, we wrap up Module 7 with Response Models and Consistent Formats.
Exercise: The Global Guard
Create a custom exception called ResourceLocked. Write an exception handler that returns a 423 Locked status code when this error is raised.