Welcome to Day 10 of the FastAPI Zero to Hero π series!
Today, we dive into something every developer faces β Errors! But instead of fearing them, let's learn how to handle them like a pro in FastAPI. πͺ
π― Why Exception Handling Matters
Think about this:
Online, you're placing a food order. The pincode you entered is not valid.
The application should gently notify you that the pincode is invalid or crash. Please give it another go."_?
It is normal to make mistakes in the real world. Effective APIs communicate what went wrong; they don't break.
Because of this, exception handling is essential for: - A pristine user experience
Improved debugging; safe and dependable APIs
βοΈ What You'll Learn Today
- Using
HTTPException
(built-in FastAPI tool) - Creating global exception handlers
- Defining your own custom exceptions like a boss πΌ
π₯ 1. Raise an HTTPException
When you want to throw a standard API error, use HTTPException
.
from fastapi import FastAPI, HTTPException
app = FastAPI()
@app.get("/items/{item_id}")
def read_item(item_id: int):
if item_id == 0:
raise HTTPException(status_code=404, detail="Item not found")
return {"item_id": item_id}
π 2. Global Exception Handler
Want to catch all ValueError
s and return a clean message instead of a scary stack trace?
Letβs register a global exception handler in FastAPI π
from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse
app = FastAPI()
# Global exception handler for ValueError
@app.exception_handler(ValueError)
async def value_error_handler(request: Request, exc: ValueError):
return JSONResponse(
status_code=400,
content={"detail": str(exc)}
)
β What comes next?
Instead of displaying the raw traceback, FastAPI will automatically utilise this handler whenever a ValueError
is raised in your application and return a tidy JSON error.
π§βπ¨ 3. Create Your Own Custom Exceptions
Built-in exceptions such as HTTPException
and ValueError
are insufficient in certain situations.
What if you require a bespoke PaymentFailedError
for your business logic?
You can create your own exception classes using FastAPI and manage them effectively with unique replies and logic.
π§± Step 1: Define Your Custom Exception
class PaymentFailedError(Exception):
def __init__(self, reason: str):
self.reason = reason
This is just a normal Python exception. You can extend it with more attributes if needed.
π§ Step 2: Register a Custom Exception Handler
from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse
app = FastAPI()
@app.exception_handler(PaymentFailedError)
async def payment_failed_handler(request: Request, exc: PaymentFailedError):
return JSONResponse(
status_code=402,
content={"detail": f"Payment failed: {exc.reason}"}
)
Here, whenever PaymentFailedError
is raised, FastAPI will use this handler to return a structured JSON response.
π Step 3: Use Your Custom Exception in a Route
@app.get("/pay")
def pay():
# Simulate a failed payment scenario
raise PaymentFailedError("Card declined by bank")
β Full FastAPI Code Example with Exception Handling
This example covers:
- πΉ Raising built-in
HTTPException
- π Global handler for
ValueError
- π§βπ¨ Custom exception:
PaymentFailedError
from fastapi import FastAPI, HTTPException, Request
from fastapi.responses import JSONResponse
app = FastAPI()
# -----------------------------------
# 1. Raise HTTPException Example
# -----------------------------------
@app.get("/items/{item_id}")
def read_item(item_id: int):
if item_id == 0:
raise HTTPException(status_code=404, detail="Item not found")
return {"item_id": item_id}
# -------------------------------------------
# 2. Global Exception Handler for ValueError
# -------------------------------------------
@app.exception_handler(ValueError)
async def value_error_handler(request: Request, exc: ValueError):
return JSONResponse(
status_code=400,
content={"detail": f"ValueError: {str(exc)}"},
)
@app.get("/divide")
def divide_numbers(a: int = 10, b: int = 0):
if b == 0:
raise ValueError("Division by zero is not allowed.")
return {"result": a / b}
# -----------------------------------
# 3. Custom Exception: PaymentFailed
# -----------------------------------
class PaymentFailedError(Exception):
def __init__(self, reason: str):
self.reason = reason
@app.exception_handler(PaymentFailedError)
async def payment_failed_handler(request: Request, exc: PaymentFailedError):
return JSONResponse(
status_code=402,
content={"detail": f"Payment failed: {exc.reason}"},
)
@app.get("/pay")
def pay():
raise PaymentFailedError("Card declined by bank")
βΆοΈ Run the FastAPI App
Use uvicorn
to run your FastAPI server locally:
uvicorn excpetions:app --host 0.0.0.0 --reload --port 9000
πΉ /items/0
β HTTPException
URL to hit:
http://localhost:9000/items/0
π /divide?a=10&b=0
β Global ValueError Handler
URL to hit:
http://localhost:9000/divide?a=10&b=0
π§βπ¨ /pay
β Custom PaymentFailedError
URL to hit:
http://localhost:9000/pay
π§Ύ Wrap-Up: Why Exception Handling Matters
Exception handling isn't just a developer convenience β it's a critical part of building reliable APIs.
In this FastAPI example, you learned how to:
β
Raise built-in exceptions like HTTPException
for standard error cases
π Register global handlers (e.g., for ValueError
) to keep your code DRY and consistent
π§βπ¨ Create custom exceptions like PaymentFailedError
to match real-world business scenarios
π Real-World Relevance
Hereβs how this maps to real-world applications:
-
HTTPException
: Missing resources like/user/0
,/product/9999
β 404 Not Found -
ValueError
: Invalid input like dividing by zero or parsing errors β 400 Bad Request -
Custom Exceptions
: Payment failures, quota limits, licensing errors β Business-specific error codes like 402 Payment Required, 429 Too Many Requests, etc.
π Pro Tip
With well-structured exception handling:
- Your API becomes more developer-friendly
- Your errors are easier to log, debug, and trace
- You leave room to plug in monitoring tools, custom logging, or even alerting systems
π Credits
Huge thanks to the FastAPI Official Documentation by SebastiΓ‘n RamΓrez (@tiangolo) β the best place to learn and explore everything about FastAPI.
π¨βπ» About Me
Hey there! Iβm Utkarsh Rastogi, an AWS Community Builder and passionate cloud-native enthusiast who loves building scalable backend systems and sharing knowledge with the community.
π Connect with me: Utkarsh Rastogi
π¬ Share Your Thoughts β I'd Love Your Feedback!
If you enjoyed today's post or learned something new, I'd truly appreciate it if you leave a comment or share your thoughts π
Your feedback, questions, or even a quick βπ₯ Loved this!β keeps me motivated to continue this journey and share more in the upcoming #FastAPIDaily posts.
β
What did you find most helpful?
β
Anything you'd like explained in the next part?
β
Suggestions for improvement? Iβm all ears! π
Letβs grow and learn together β one FastAPI day at a time π
Top comments (0)