"""Custom exceptions for the API.""" from fastapi import HTTPException, status class APIException(HTTPException): """Base API exception with structured error format.""" def __init__( self, status_code: int, message: str, field: str = None, code: str = None, detail: str = None ): self.message = message self.field = field self.code = code or self._get_default_code(status_code) super().__init__(status_code=status_code, detail=detail or message) def _get_default_code(self, status_code: int) -> str: """Get default error code based on status code.""" codes = { 400: "BAD_REQUEST", 401: "UNAUTHORIZED", 403: "FORBIDDEN", 404: "NOT_FOUND", 409: "CONFLICT", 422: "VALIDATION_ERROR", 429: "RATE_LIMIT_EXCEEDED", 500: "INTERNAL_SERVER_ERROR", 503: "SERVICE_UNAVAILABLE" } return codes.get(status_code, "UNKNOWN_ERROR") class ValidationError(APIException): """Validation error exception.""" def __init__(self, message: str, field: str = None): super().__init__( status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, message=message, field=field, code="VALIDATION_ERROR" ) class NotFoundError(APIException): """Resource not found exception.""" def __init__(self, message: str = "Resource not found"): super().__init__( status_code=status.HTTP_404_NOT_FOUND, message=message, code="NOT_FOUND" ) class RateLimitError(APIException): """Rate limit exceeded exception.""" def __init__(self, message: str = "Rate limit exceeded"): super().__init__( status_code=status.HTTP_429_TOO_MANY_REQUESTS, message=message, code="RATE_LIMIT_EXCEEDED" )