Error Handling

Loading concept...

🚦 FastAPI Error Handling: Your App’s Safety Net

Imagine you’re a traffic controller at a busy intersection. When cars follow the rules, everything flows smoothly. But when something goes wrong—a car runs a red light, takes a wrong turn, or breaks down—you need to stop traffic, signal the problem, and guide everyone safely. That’s exactly what error handling does in FastAPI!


🎯 What You’ll Learn

We’re going to explore three superpowers that help your FastAPI app handle problems gracefully:

  1. HTTPException – The “stop sign” that tells users something went wrong
  2. Custom Exception Handlers – Your personal traffic controller for specific problems
  3. Validation Errors – The gatekeeper that checks if data looks right before letting it in

🛑 HTTPException: The Stop Sign

What Is It?

Think of HTTPException as a big red STOP sign. When your app can’t do what someone asked, it raises this exception to say: “Hey! Something’s not right here!”

Real Life Example

Imagine a library app. A user asks for Book #999, but that book doesn’t exist.

from fastapi import FastAPI, HTTPException

app = FastAPI()

books = {1: "Harry Potter", 2: "Lord of Rings"}

@app.get("/books/{book_id}")
def get_book(book_id: int):
    if book_id not in books:
        raise HTTPException(
            status_code=404,
            detail="Book not found!"
        )
    return {"book": books[book_id]}

What Happens?

  • User asks for /books/999
  • Book #999 doesn’t exist
  • App raises HTTPException with code 404
  • User sees: {"detail": "Book not found!"}

Common Status Codes (Like Traffic Signs!)

Code Meaning When to Use
400 Bad Request User sent broken data
401 Unauthorized User needs to log in
403 Forbidden User can’t access this
404 Not Found Thing doesn’t exist
500 Server Error Something broke inside

Adding Extra Information

You can add headers to give more details:

raise HTTPException(
    status_code=401,
    detail="Invalid token",
    headers={"WWW-Authenticate": "Bearer"}
)

🎨 Custom Exception Handlers: Your Personal Traffic Controller

What Is It?

Sometimes the default stop sign isn’t enough. You want to handle specific problems in your own special way. Custom Exception Handlers let you create your own traffic controllers!

The Story

Imagine your app has a special rule: Users can only ask for 3 things per minute. When they ask for more, you want to give a friendly message—not a scary error.

Step 1: Create Your Own Exception

class TooManyRequestsError(Exception):
    def __init__(self, wait_time: int):
        self.wait_time = wait_time

Step 2: Create the Handler

from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse

app = FastAPI()

@app.exception_handler(TooManyRequestsError)
async def too_many_handler(
    request: Request,
    exc: TooManyRequestsError
):
    return JSONResponse(
        status_code=429,
        content={
            "message": "Slow down, friend!",
            "wait_seconds": exc.wait_time,
            "tip": "Grab a coffee ☕"
        }
    )

Step 3: Use It!

@app.get("/data")
def get_data():
    # If user made too many requests...
    raise TooManyRequestsError(wait_time=30)

What User Sees

{
    "message": "Slow down, friend!",
    "wait_seconds": 30,
    "tip": "Grab a coffee ☕"
}

Much nicer than a scary error message!

Flow Diagram

graph TD A[User Request] --> B{Check Rules} B -->|OK| C[Return Data] B -->|Too Many| D[Raise TooManyRequestsError] D --> E[Custom Handler Catches It] E --> F[Friendly JSON Response]

✅ Validation Errors: The Gatekeeper

What Is It?

Validation Errors happen when someone sends data that doesn’t match what you expected. It’s like a gatekeeper checking IDs at the door!

The Story

Your app expects a user’s age. Someone types “twenty” instead of “20”. The gatekeeper says: “Sorry, that’s not a number!”

How FastAPI Validates

FastAPI uses Pydantic to check data automatically:

from pydantic import BaseModel

class User(BaseModel):
    name: str
    age: int
    email: str

@app.post("/users")
def create_user(user: User):
    return {"created": user.name}

What Happens With Bad Data?

If someone sends:

{"name": "Alex", "age": "twenty", "email": "alex@mail"}

FastAPI automatically responds:

{
    "detail": [
        {
            "loc": ["body", "age"],
            "msg": "value is not a valid integer",
            "type": "type_error.integer"
        }
    ]
}

Making Validation Errors Prettier

You can customize how validation errors look:

from fastapi.exceptions import RequestValidationError

@app.exception_handler(RequestValidationError)
async def validation_handler(
    request: Request,
    exc: RequestValidationError
):
    errors = []
    for error in exc.errors():
        field = error["loc"][-1]
        errors.append({
            "field": field,
            "problem": error["msg"]
        })

    return JSONResponse(
        status_code=422,
        content={
            "message": "Oops! Check your data",
            "errors": errors
        }
    )

Now User Sees

{
    "message": "Oops! Check your data",
    "errors": [
        {"field": "age", "problem": "value is not a valid integer"}
    ]
}

Common Validation Types

Check Example What It Does
int age: int Must be a number
str name: str Must be text
EmailStr email: EmailStr Must look like email
gt=0 Field(gt=0) Must be greater than 0
max_length Field(max_length=50) Can’t be too long

🔄 Putting It All Together

Here’s a complete mini-app showing all three concepts:

from fastapi import FastAPI, HTTPException, Request
from fastapi.responses import JSONResponse
from fastapi.exceptions import RequestValidationError
from pydantic import BaseModel, Field

app = FastAPI()

# 1. Custom Exception
class RateLimitError(Exception):
    def __init__(self, seconds: int):
        self.seconds = seconds

# 2. Custom Handler for RateLimitError
@app.exception_handler(RateLimitError)
async def rate_limit_handler(req: Request, exc: RateLimitError):
    return JSONResponse(
        status_code=429,
        content={"wait": exc.seconds}
    )

# 3. Custom Handler for ValidationError
@app.exception_handler(RequestValidationError)
async def validation_handler(req: Request, exc: RequestValidationError):
    return JSONResponse(
        status_code=422,
        content={"errors": "Check your input!"}
    )

# 4. Data Model with Validation
class Item(BaseModel):
    name: str = Field(min_length=1)
    price: float = Field(gt=0)

items_db = {1: "Apple", 2: "Banana"}

@app.get("/items/{item_id}")
def get_item(item_id: int):
    # HTTPException example
    if item_id not in items_db:
        raise HTTPException(
            status_code=404,
            detail="Item not found"
        )
    return {"item": items_db[item_id]}

@app.post("/items")
def create_item(item: Item):
    # Validation happens automatically!
    return {"created": item.name}

🎯 Quick Summary

Concept What It Does When to Use
HTTPException Stops and returns error Item not found, access denied
Custom Handlers Your own error responses Special business rules
Validation Errors Checks incoming data Wrong data types, missing fields

💡 Pro Tips

  1. Always be friendly – Users should understand what went wrong
  2. Use the right status code – 404 for “not found”, 400 for “bad request”
  3. Don’t expose secrets – Never show database errors to users
  4. Log errors – Save detailed errors for yourself, show simple ones to users

🚀 You Did It!

You now know how to:

  • ✅ Stop bad requests with HTTPException
  • ✅ Create custom responses with Exception Handlers
  • ✅ Automatically check data with Validation Errors

Your FastAPI app is now a well-controlled intersection where everything flows smoothly—and when problems happen, everyone knows exactly what to do!

Happy coding! 🎉

Loading story...

No Story Available

This concept doesn't have a story yet.

Story Preview

Story - Premium Content

Please sign in to view this concept and start learning.

Upgrade to Premium to unlock full access to all content.

Interactive Preview

Interactive - Premium Content

Please sign in to view this concept and start learning.

Upgrade to Premium to unlock full access to all content.

No Interactive Content

This concept doesn't have interactive content yet.

Cheatsheet Preview

Cheatsheet - Premium Content

Please sign in to view this concept and start learning.

Upgrade to Premium to unlock full access to all content.

No Cheatsheet Available

This concept doesn't have a cheatsheet yet.

Quiz Preview

Quiz - Premium Content

Please sign in to view this concept and start learning.

Upgrade to Premium to unlock full access to all content.

No Quiz Available

This concept doesn't have a quiz yet.