Skip to content

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 errors
  • ApiErrorCodes: Enum of standard error codes for consistency
  • ErrorResponse: TypedDict for structured error responses
  • api_error_exception(): Helper to create API error exceptions
  • construct_api_error_exception(): Convert any exception to API error
  • inject_api_error_handler(): Register error handler with FastAPI

Installation

The error handler module is part of the dcc-backend-common package:

bash
uv add ddc-backend-common

Quick Start

python
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 CodeDescriptionTypical Status
UNEXPECTED_ERRORUnexpected server error500
SERVICE_UNAVAILABLEService temporarily unavailable503
INVALID_REQUESTInvalid request parameters400
AUTHENTICATION_FAILEDAuthentication failed401
PERMISSION_DENIEDAccess denied403
RESOURCE_NOT_FOUNDResource does not exist404
RATE_LIMIT_EXCEEDEDToo many requests429
VALIDATION_ERRORInput validation failed422

Error Exception

ApiErrorException

Custom exception that holds a structured error response.

python
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 error

ErrorResponse

TypedDict structure for error responses:

python
class ErrorResponse(TypedDict, total=False):
    errorId: str | ApiErrorCodes
    status: int | None  # defaults to 500
    debugMessage: str | None

Helper Functions

api_error_exception()

Create an ApiErrorException with parameters.

python
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 to UNEXPECTED_ERROR
  • status (int): HTTP status code, defaults to 500
  • debugMessage (str | None): Optional debug message

construct_api_error_exception()

Convert any exception to an ApiErrorException.

python
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_error

Parameters:

  • exception (Exception): Original exception to convert
  • error_id (str | ApiErrorCodes): Error identifier, defaults to UNEXPECTED_ERROR
  • status_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.

python
from dcc_backend_common.fastapi_error_handling import inject_api_error_handler

app = FastAPI()
inject_api_error_handler(app)

The handler:

  • Catches ApiErrorException and 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:

json
{
  "errorId": "resource_not_found",
  "status": 404,
  "debugMessage": "User not found"
}

Response fields:

  • errorId (str): Error code from ApiErrorCodes or custom string
  • status (int): HTTP status code
  • debugMessage (string | null): Optional debug information

API Reference

Source Code

The full implementation is available on GitHub:

Developed with ❤️ by the DCC. Documentation released under the MIT License.