Error Handler
The dcc_backend_common.fastapi_error_handling module provides a standardized way to handle and format API errors across all FastAPI services.
Overview
The module provides:
ApiErrorException: Custom exception class for API errorsApiErrorCodes: Enum of standard error codes for consistencyErrorResponse: TypedDict for structured error responsesapi_error_exception(): Helper to create API error exceptionsconstruct_api_error_exception(): Convert any exception to API errorinject_api_error_handler(): Register error handler with FastAPI
Installation
The error handler module is part of the dcc-backend-common package:
uv add ddc-backend-commonQuick Start
from contextlib import asynccontextmanager
from fastapi import FastAPI
from dcc_backend_common.fastapi_error_handling import (
ApiErrorException,
ApiErrorCodes,
api_error_exception,
inject_api_error_handler,
)
@asynccontextmanager
async def lifespan(app: FastAPI):
"""Application lifespan handler."""
inject_api_error_handler(app) # Register error handler
yield
app = FastAPI(lifespan=lifespan)
@app.get("/users/{user_id}")
async def get_user(user_id: int):
if user_id < 1:
raise api_error_exception(
errorId=ApiErrorCodes.INVALID_REQUEST,
status=400,
debugMessage="User ID must be positive",
)
return {"id": user_id, "name": "John Doe"}Error Codes
The ApiErrorCodes enum provides standard error codes:
| Error Code | Description | Typical Status |
|---|---|---|
UNEXPECTED_ERROR | Unexpected server error | 500 |
SERVICE_UNAVAILABLE | Service temporarily unavailable | 503 |
INVALID_REQUEST | Invalid request parameters | 400 |
AUTHENTICATION_FAILED | Authentication failed | 401 |
PERMISSION_DENIED | Access denied | 403 |
RESOURCE_NOT_FOUND | Resource does not exist | 404 |
RATE_LIMIT_EXCEEDED | Too many requests | 429 |
VALIDATION_ERROR | Input validation failed | 422 |
Error Exception
ApiErrorException
Custom exception that holds a structured error response.
from dcc_backend_common.fastapi_error_handling import ApiErrorException, ApiErrorCodes
# Create directly
error = ApiErrorException(
error_response={
"errorId": ApiErrorCodes.RESOURCE_NOT_FOUND,
"status": 404,
"debugMessage": "User not found",
}
)
raise errorErrorResponse
TypedDict structure for error responses:
class ErrorResponse(TypedDict, total=False):
errorId: str | ApiErrorCodes
status: int | None # defaults to 500
debugMessage: str | NoneHelper Functions
api_error_exception()
Create an ApiErrorException with parameters.
from dcc_backend_common.fastapi_error_handling import api_error_exception, ApiErrorCodes
raise api_error_exception(
errorId=ApiErrorCodes.VALIDATION_ERROR,
status=422,
debugMessage="Email format is invalid",
)Parameters:
errorId(str | ApiErrorCodes): Error identifier, defaults toUNEXPECTED_ERRORstatus(int): HTTP status code, defaults to 500debugMessage(str | None): Optional debug message
construct_api_error_exception()
Convert any exception to an ApiErrorException.
from dcc_backend_common.fastapi_error_handling import construct_api_error_exception, ApiErrorCodes
try:
result = risky_operation()
except ValueError as e:
api_error = construct_api_error_exception(
exception=e,
error_id=ApiErrorCodes.VALIDATION_ERROR,
status_code=422,
)
raise api_errorParameters:
exception(Exception): Original exception to converterror_id(str | ApiErrorCodes): Error identifier, defaults toUNEXPECTED_ERRORstatus_code(int | None): Optional HTTP status code
Note: If status_code is not provided and the exception is a HTTPException, the status code from the exception is used.
Handler Integration
inject_api_error_handler()
Register the error handler with your FastAPI application.
from dcc_backend_common.fastapi_error_handling import inject_api_error_handler
app = FastAPI()
inject_api_error_handler(app)The handler:
- Catches
ApiErrorExceptionand returns its structured response - Catches other exceptions and returns a 500 response with
UNEXPECTED_ERROR
API Response Format
All errors are returned in a consistent JSON format:
{
"errorId": "resource_not_found",
"status": 404,
"debugMessage": "User not found"
}Response fields:
errorId(str): Error code fromApiErrorCodesor custom stringstatus(int): HTTP status codedebugMessage(string | null): Optional debug information
Related Documentation
- Configuration - Manage application configuration
- Logger - Structured logging with structlog
- Python Coding Standards - General Python best practices
API Reference
Source Code
The full implementation is available on GitHub:
