FastAPI uses the HTTPException
class to raise HTTP errors. This class is part of the fastapi
library and allows you to return an HTTP response with a specific status code and an optional error message.
from fastapi import FastAPI, HTTPException
app = FastAPI()
@app.get("/items/{item_id}")
async def read_item(item_id: int):
if item_id not in [1, 2, 3]:
raise HTTPException(status_code=404, detail="Item not found")
return {"item_id": item_id, "name": f"Item {item_id}"}
In this example, if the item_id
is not in the list [1, 2, 3]
, a 404 Not Found
error is raised with a custom error message.
FastAPI allows you to define custom exception handlers to handle specific types of exceptions. You can use the @app.exception_handler()
decorator to register a function that will be called when a particular exception occurs.
from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse
app = FastAPI()
class CustomException(Exception):
def __init__(self, message: str):
self.message = message
@app.exception_handler(CustomException)
async def custom_exception_handler(request: Request, exc: CustomException):
return JSONResponse(
status_code=400,
content={"message": f"Custom error: {exc.message}"},
)
@app.get("/custom_error")
async def trigger_custom_error():
raise CustomException(message="This is a custom error")
In this example, we define a custom exception CustomException
and a custom exception handler for it. When the /custom_error
endpoint is called, the custom exception is raised, and the custom exception handler returns a JSON response with a 400 Bad Request
status code and a custom error message.
To raise an HTTPException
, you simply need to import the class and call it with the appropriate status code and error message.
from fastapi import FastAPI, HTTPException
app = FastAPI()
@app.post("/login")
async def login(username: str, password: str):
if username != "admin" or password != "password":
raise HTTPException(status_code=401, detail="Invalid credentials")
return {"message": "Login successful"}
To register a custom exception handler, use the @app.exception_handler()
decorator followed by the exception class you want to handle.
from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse
app = FastAPI()
class DatabaseError(Exception):
pass
@app.exception_handler(DatabaseError)
async def database_error_handler(request: Request, exc: DatabaseError):
return JSONResponse(
status_code=500,
content={"message": "Database error occurred"}
)
@app.get("/database_error")
async def trigger_database_error():
raise DatabaseError()
It is a good practice to return errors in a consistent format. For example, you can use a JSON object with a message
field to convey the error information.
from fastapi import FastAPI, HTTPException
app = FastAPI()
@app.get("/consistent_error")
async def consistent_error():
raise HTTPException(status_code=403, detail={"message": "Forbidden access"})
Logging errors is essential for debugging and monitoring. You can use the Python logging
module to log errors in your FastAPI application.
import logging
from fastapi import FastAPI, HTTPException
app = FastAPI()
logging.basicConfig(level=logging.ERROR)
@app.get("/log_error")
async def log_error():
try:
result = 1 / 0
except ZeroDivisionError as e:
logging.error(f"Zero division error: {e}")
raise HTTPException(status_code=500, detail="Internal server error")
return {"result": result}
Instead of using generic exceptions, use specific exception types to make your code more readable and maintainable.
from fastapi import FastAPI, HTTPException
app = FastAPI()
class UserNotFoundError(Exception):
pass
@app.get("/user/{user_id}")
async def get_user(user_id: int):
if user_id not in [1, 2, 3]:
raise UserNotFoundError()
return {"user_id": user_id, "name": f"User {user_id}"}
@app.exception_handler(UserNotFoundError)
async def user_not_found_handler(request, exc):
return HTTPException(status_code=404, detail="User not found")
Error messages should be clear and concise, providing enough information for the client to understand the problem.
from fastapi import FastAPI, HTTPException
app = FastAPI()
@app.get("/clear_message")
async def clear_message():
raise HTTPException(status_code=400, detail="The provided input is invalid. Please check your data.")
Error management is a critical part of building reliable and user-friendly APIs. FastAPI provides powerful tools such as HTTPException
and custom exception handlers to handle errors effectively. By following the common practices and best practices outlined in this blog, you can ensure that your FastAPI application gracefully handles errors, provides meaningful feedback to clients, and is easy to maintain and debug.