python
34 lines · 7 steps
Custom exception handlers in FastAPI
Map a domain-specific exception to a structured HTTP error response so route handlers can fail by raising, not by formatting JSON.
Explained by
highlit
1from fastapi import FastAPI, Request, status
2from fastapi.responses import JSONResponse
3
4app = FastAPI()
5
6
7class InsufficientFundsError(Exception):
8 def __init__(self, account_id: str, balance: float, requested: float):
9 self.account_id = account_id
10 self.balance = balance
11 self.requested = requested
12
13
14@app.exception_handler(InsufficientFundsError)
15async def insufficient_funds_handler(request: Request, exc: InsufficientFundsError):
16 return JSONResponse(
17 status_code=status.HTTP_402_PAYMENT_REQUIRED,
18 content={
19 "error": "insufficient_funds",
20 "message": f"Account {exc.account_id} cannot withdraw {exc.requested:.2f}.",
21 "available_balance": exc.balance,
22 "shortfall": round(exc.requested - exc.balance, 2),
23 },
24 headers={"X-Error-Code": "INSUFFICIENT_FUNDS"},
25 )
26
27
28@app.post("/accounts/{account_id}/withdraw")
29async def withdraw(account_id: str, amount: float):
30 account = await accounts.get(account_id)
31 if amount > account.balance:
32 raise InsufficientFundsError(account_id, account.balance, amount)
33 await account.debit(amount)
34 return {"account_id": account_id, "balance": account.balance - amount}
01 / 01
STEP 01
‹ swipe to step through ›
Walkthrough
Space play
←→ step
click any line
Three takeaways
- 1Centralizing error formatting in a handler keeps route logic focused on the happy path.
- 2A custom exception can carry rich context that the handler turns into a meaningful response.
- 3Mapping domain failures to specific status codes makes an API's errors predictable for clients.
Related explainers
python
from fastapi import FastAPI, WebSocket, WebSocketDisconnect app = FastAPI()
Building a WebSocket chat with FastAPI
websockets
broadcast
connection-management
Intermediate
9 steps
python
import time import uuid from django.utils.deprecation import MiddlewareMixin
Attaching per-request context in Django
middleware
request lifecycle
multi-tenancy
Intermediate
7 steps
python
import random from typing import Iterator, List
How reservoir sampling picks k items
reservoir-sampling
streaming
randomness
Intermediate
5 steps
python
import secrets from django.contrib.auth import authenticate, login from django.core.cache import cache
Two-factor login with OTP in Django
two-factor-auth
one-time-passwords
caching
Intermediate
9 steps
python
import re from functools import total_ordering from typing import Optional
Parsing and comparing semantic versions
regex
operator-overloading
sorting
Intermediate
7 steps
python
from typing import Any, Sequence, Mapping def render_markdown_table(
Rendering an aligned Markdown table in Python
string formatting
data transformation
closures
Intermediate
8 steps
Share this explainer
Here's the card — post it anywhere.
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code
Embed this explainer
Drop the interactive walkthrough into a blog or docs. Views never cost a credit.
<iframe src="https://highlit.co/explainers/custom-exception-handlers-in-fastapi-explained-python-3b95/embed?autoplay=1" width="100%" height="520" loading="lazy" style="border:0"></iframe>
Autoplay is on by default — add ?autoplay=0 to start paused.