Skip to content

Error Handling

santiago edited this page Jan 29, 2026 · 1 revision

Error Handling

The framework provides custom exceptions and error handling patterns.

Custom Exceptions

The framework includes two custom exceptions:

NotFoundError

Raised when a service is not registered in the container:

from azfunc_boot import NotFoundError

try:
    service = container.get_service(IService)
except NotFoundError as e:
    logger.error(f"Service not found: {e}")
    # Handle the error

ValidationError

Raised for validation failures:

from azfunc_boot import ValidationError

def validate_user_data(data: dict):
    if not data.get("email"):
        raise ValidationError("Email is required")
    
    if "@" not in data["email"]:
        raise ValidationError("Invalid email format")

Error Handling in Controllers

Handle errors in your controller methods:

import logging
from azfunc_boot import BaseController, NotFoundError, ValidationError
import azure.functions as func

class UserController(BaseController):
    def __init__(self, container: DependencyContainer, bp: func.Blueprint):
        super().__init__(container, bp)
        self._logger = logging.getLogger(__name__)

    async def get_user(self, req: func.HttpRequest) -> func.HttpResponse:
        try:
            user_id = req.route_params.get("id")
            user_service = self.container.get_service(IUserService)
            user = await user_service.get_by_id(user_id)
            
            if not user:
                return func.HttpResponse("User not found", status_code=404)
            
            return func.HttpResponse(
                json.dumps(user.to_dict()),
                status_code=200,
                mimetype="application/json"
            )
        except NotFoundError as e:
            self._logger.warning(f"Service not found: {e}")
            return func.HttpResponse(
                "Service unavailable", 
                status_code=503
            )
        except ValidationError as e:
            self._logger.warning(f"Validation error: {e}")
            return func.HttpResponse(
                f"Validation error: {e}", 
                status_code=400
            )
        except Exception as e:
            self._logger.error(f"Unexpected error: {e}", exc_info=True)
            return func.HttpResponse(
                "Internal server error", 
                status_code=500
            )

Global Error Handling

You can create a middleware or wrapper for global error handling:

from functools import wraps
from azfunc_boot import NotFoundError, ValidationError
import azure.functions as func

def handle_errors(func_handler):
    @wraps(func_handler)
    async def wrapper(req: func.HttpRequest) -> func.HttpResponse:
        try:
            return await func_handler(req)
        except NotFoundError as e:
            return func.HttpResponse(
                f"Resource not found: {e}",
                status_code=404
            )
        except ValidationError as e:
            return func.HttpResponse(
                f"Validation error: {e}",
                status_code=400
            )
        except Exception as e:
            logger.error(f"Unhandled error: {e}", exc_info=True)
            return func.HttpResponse(
                "Internal server error",
                status_code=500
            )
    return wrapper

# Usage
class MyController(BaseController):
    def register_routes(self):
        self.bp.route(
            self.PATH, 
            methods=["GET"]
        )(handle_errors(self.my_method))

Service-Level Error Handling

Handle errors in your services:

from azfunc_boot import NotFoundError, ValidationError

class UserService:
    def __init__(self, repository: IUserRepository):
        self.repository = repository
    
    async def get_by_id(self, user_id: str):
        if not user_id:
            raise ValidationError("User ID is required")
        
        user = await self.repository.find_by_id(user_id)
        if not user:
            raise NotFoundError(f"User with ID {user_id} not found")
        
        return user

Logging Errors

Always log errors for debugging:

import logging

logger = logging.getLogger(__name__)

try:
    # Your code
    pass
except NotFoundError as e:
    logger.warning(f"Resource not found: {e}")
    # Handle error
except ValidationError as e:
    logger.warning(f"Validation failed: {e}")
    # Handle error
except Exception as e:
    logger.error(f"Unexpected error: {e}", exc_info=True)
    # Handle error

HTTP Status Codes

Use appropriate HTTP status codes:

  • 400 Bad Request: Validation errors, malformed requests
  • 404 Not Found: Resource not found
  • 500 Internal Server Error: Unexpected errors
  • 503 Service Unavailable: Service dependencies unavailable

Best Practices

  1. Catch specific exceptions: Use specific exception types rather than catching all exceptions
  2. Log errors: Always log errors with appropriate levels (warning, error, critical)
  3. Return appropriate status codes: Use HTTP status codes that match the error type
  4. Don't expose internal details: In production, don't return detailed error messages to clients
  5. Use custom exceptions: Create domain-specific exceptions when needed

Related Topics

Clone this wiki locally