CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-sanic

A modern Python web server and web framework designed for high performance and speed using async/await syntax.

Pending
Overview
Eval results
Files

exceptions.mddocs/

Exception Handling

Sanic provides a comprehensive exception system with HTTP status code exceptions, custom error handlers, and mechanisms for graceful error handling. The framework includes built-in exceptions for common HTTP errors and supports custom exception handling.

Capabilities

Base Exception Classes

Core exception classes that form the foundation of Sanic's error handling system.

class SanicException(Exception):
    """
    Base exception class for all Sanic exceptions.
    
    Attributes:
    - message: Exception message
    - status_code: HTTP status code (if applicable)
    - quiet: Whether to suppress logging
    """
    
    def __init__(
        self,
        message: str,
        status_code: int = None,
        quiet: bool = None,
        context: dict = None,
        extra: dict = None,
    ):
        """
        Initialize Sanic exception.
        
        Parameters:
        - message: Error message
        - status_code: HTTP status code
        - quiet: Suppress logging if True
        - context: Additional context information
        - extra: Extra data for exception
        """

class ServerError(SanicException):
    """
    Base class for 5xx server error exceptions.
    
    Default status_code: 500
    """

class InvalidUsage(SanicException):
    """
    Base class for 4xx client error exceptions.
    
    Default status_code: 400
    """

HTTP Client Error Exceptions (4xx)

Exceptions for client-side errors with appropriate HTTP status codes.

class BadRequest(InvalidUsage):
    """
    400 Bad Request exception.
    
    Raised when the request is malformed or invalid.
    """
    
    def __init__(self, message: str = "Bad Request", **kwargs):
        super().__init__(message, status_code=400, **kwargs)

class Unauthorized(InvalidUsage):
    """
    401 Unauthorized exception.
    
    Raised when authentication is required but missing or invalid.
    """
    
    def __init__(self, message: str = "Unauthorized", **kwargs):
        super().__init__(message, status_code=401, **kwargs)

class Forbidden(InvalidUsage):
    """
    403 Forbidden exception.
    
    Raised when the request is understood but access is denied.
    """
    
    def __init__(self, message: str = "Forbidden", **kwargs):
        super().__init__(message, status_code=403, **kwargs)

class NotFound(InvalidUsage):
    """
    404 Not Found exception.
    
    Raised when the requested resource cannot be found.
    """
    
    def __init__(self, message: str = "Not Found", **kwargs):
        super().__init__(message, status_code=404, **kwargs)

class MethodNotAllowed(InvalidUsage):
    """
    405 Method Not Allowed exception.
    
    Raised when the HTTP method is not allowed for the resource.
    """
    
    def __init__(self, message: str = "Method Not Allowed", **kwargs):
        super().__init__(message, status_code=405, **kwargs)

class RangeNotSatisfiable(InvalidUsage):
    """
    416 Range Not Satisfiable exception.
    
    Raised when the requested range cannot be satisfied.
    """
    
    def __init__(self, message: str = "Range Not Satisfiable", **kwargs):
        super().__init__(message, status_code=416, **kwargs)

class ExpectationFailed(InvalidUsage):
    """
    417 Expectation Failed exception.
    
    Raised when the server cannot meet the Expect request header requirements.
    """
    
    def __init__(self, message: str = "Expectation Failed", **kwargs):
        super().__init__(message, status_code=417, **kwargs)

class PayloadTooLarge(InvalidUsage):
    """
    413 Payload Too Large exception.
    
    Raised when the request payload exceeds size limits.
    """
    
    def __init__(self, message: str = "Payload Too Large", **kwargs):
        super().__init__(message, status_code=413, **kwargs)

class RequestTimeout(InvalidUsage):
    """
    408 Request Timeout exception.
    
    Raised when the request takes too long to process.
    """
    
    def __init__(self, message: str = "Request Timeout", **kwargs):
        super().__init__(message, status_code=408, **kwargs)

HTTP Server Error Exceptions (5xx)

Exceptions for server-side errors indicating internal problems.

class InternalServerError(ServerError):
    """
    500 Internal Server Error exception.
    
    Raised when an unexpected server error occurs.
    """
    
    def __init__(self, message: str = "Internal Server Error", **kwargs):
        super().__init__(message, status_code=500, **kwargs)

class ServiceUnavailable(ServerError):
    """
    503 Service Unavailable exception.
    
    Raised when the server is temporarily unable to handle requests.
    """
    
    def __init__(self, message: str = "Service Unavailable", **kwargs):
        super().__init__(message, status_code=503, **kwargs)

class NotImplemented(ServerError):
    """
    501 Not Implemented exception.
    
    Raised when the requested functionality is not implemented.
    """
    
    def __init__(self, message: str = "Not Implemented", **kwargs):
        super().__init__(message, status_code=501, **kwargs)

class BadGateway(ServerError):
    """
    502 Bad Gateway exception.
    
    Raised when acting as gateway and receiving invalid response.
    """
    
    def __init__(self, message: str = "Bad Gateway", **kwargs):
        super().__init__(message, status_code=502, **kwargs)

class GatewayTimeout(ServerError):
    """
    504 Gateway Timeout exception.
    
    Raised when acting as gateway and upstream server times out.
    """
    
    def __init__(self, message: str = "Gateway Timeout", **kwargs):
        super().__init__(message, status_code=504, **kwargs)

Specialized Exceptions

Framework-specific exceptions for particular scenarios and conditions.

class HeaderNotFound(SanicException):
    """
    Raised when a required header is missing from the request.
    """
    
    def __init__(self, message: str = "Header not found", **kwargs):
        super().__init__(message, **kwargs)

class InvalidHeader(SanicException):
    """
    Raised when a header value is invalid or malformed.
    """
    
    def __init__(self, message: str = "Invalid header", **kwargs):
        super().__init__(message, **kwargs)

class FileNotFound(NotFound):
    """
    Raised when a requested file cannot be found.
    """
    
    def __init__(self, message: str = "File not found", **kwargs):
        super().__init__(message, **kwargs)

class WebsocketClosed(SanicException):
    """
    Raised when attempting to use a closed WebSocket connection.
    """
    
    def __init__(self, message: str = "WebSocket connection closed", **kwargs):
        super().__init__(message, **kwargs)

class InvalidSignal(SanicException):
    """
    Raised when an invalid signal is used.
    """
    
    def __init__(self, message: str = "Invalid signal", **kwargs):
        super().__init__(message, **kwargs)

class ContentRangeError(SanicException):
    """
    Raised when there's an error with content range handling.
    """
    
    def __init__(self, message: str = "Content range error", **kwargs):
        super().__init__(message, **kwargs)

class HeaderExpectationFailed(SanicException):
    """
    Raised when header expectations cannot be met.
    """
    
    def __init__(self, message: str = "Header expectation failed", **kwargs):
        super().__init__(message, **kwargs)

class MethodNotSupported(SanicException):
    """
    Raised when an unsupported HTTP method is used.
    """
    
    def __init__(self, message: str = "Method not supported", **kwargs):
        super().__init__(message, **kwargs)

Exception Handlers

Decorators and methods for registering custom exception handlers.

def exception(*exceptions):
    """
    Decorator for registering exception handlers.
    
    Parameters:
    - *exceptions: Exception classes to handle
    
    Usage:
    @app.exception(NotFound, FileNotFound)
    async def handle_not_found(request, exception):
        return json({"error": "Resource not found"}, status=404)
    """

class ErrorHandler:
    """Error handler management for applications and blueprints."""
    
    def add(self, exception, handler):
        """
        Add exception handler.
        
        Parameters:
        - exception: Exception class
        - handler: Handler function
        """
    
    def lookup(self, exception, route_name: str = None):
        """
        Look up handler for exception.
        
        Parameters:
        - exception: Exception instance
        - route_name: Route name for context
        
        Returns:
        Handler function or None
        """
    
    def response(self, request, exception):
        """
        Generate response for exception.
        
        Parameters:
        - request: Request object
        - exception: Exception instance
        
        Returns:
        HTTPResponse object
        """

Usage Examples

Basic Exception Handling

from sanic import Sanic
from sanic.response import json
from sanic.exceptions import NotFound, ServerError, BadRequest

app = Sanic("MyApp")

@app.route("/users/<user_id:int>")
async def get_user(request, user_id):
    user = await fetch_user(user_id)
    if not user:
        raise NotFound("User not found")
    return json({"user": user})

@app.route("/api/data", methods=["POST"])
async def process_data(request):
    if not request.json:
        raise BadRequest("JSON data required")
    
    try:
        result = await process_user_data(request.json)
        return json({"result": result})
    except ValueError as e:
        raise BadRequest(f"Invalid data: {str(e)}")
    except Exception as e:
        raise ServerError("Processing failed")

Custom Exception Handlers

from sanic import Sanic
from sanic.response import json
from sanic.exceptions import NotFound, ServerError, SanicException

app = Sanic("MyApp")

@app.exception(NotFound)
async def handle_not_found(request, exception):
    return json({
        "error": "Resource not found",
        "message": str(exception),
        "path": request.path
    }, status=404)

@app.exception(ServerError)
async def handle_server_error(request, exception):
    # Log the error
    app.logger.error(f"Server error: {exception}")
    
    return json({
        "error": "Internal server error",
        "message": "An unexpected error occurred"
    }, status=500)

@app.exception(SanicException)
async def handle_sanic_exception(request, exception):
    """Catch-all handler for Sanic exceptions."""
    return json({
        "error": "Application error",
        "message": str(exception),
        "status_code": getattr(exception, "status_code", 500)
    }, status=getattr(exception, "status_code", 500))

Custom Exception Classes

from sanic.exceptions import SanicException
from sanic.response import json

class ValidationError(SanicException):
    \"\"\"Custom validation error exception.\"\"\"
    
    def __init__(self, message: str, field: str = None, **kwargs):
        super().__init__(message, status_code=422, **kwargs)
        self.field = field

class AuthenticationError(SanicException):
    \"\"\"Custom authentication error exception.\"\"\"
    
    def __init__(self, message: str = "Authentication failed", **kwargs):
        super().__init__(message, status_code=401, **kwargs)

class RateLimitExceeded(SanicException):
    \"\"\"Custom rate limit exception.\"\"\"
    
    def __init__(self, message: str = "Rate limit exceeded", retry_after: int = None, **kwargs):
        super().__init__(message, status_code=429, **kwargs)
        self.retry_after = retry_after

# Register handlers for custom exceptions
@app.exception(ValidationError)
async def handle_validation_error(request, exception):
    return json({
        "error": "Validation failed",
        "message": str(exception),
        "field": getattr(exception, "field", None)
    }, status=422)

@app.exception(AuthenticationError)
async def handle_auth_error(request, exception):
    return json({
        "error": "Authentication required",
        "message": str(exception)
    }, status=401)

@app.exception(RateLimitExceeded)
async def handle_rate_limit(request, exception):
    headers = {}
    if hasattr(exception, "retry_after"):
        headers["Retry-After"] = str(exception.retry_after)
    
    return json({
        "error": "Rate limit exceeded",
        "message": str(exception)
    }, status=429, headers=headers)

Exception Context and Debugging

from sanic import Sanic
from sanic.response import json
from sanic.exceptions import SanicException

app = Sanic("MyApp")

class DatabaseError(SanicException):
    \"\"\"Database operation error with context.\"\"\"
    
    def __init__(self, message: str, query: str = None, **kwargs):
        context = {"query": query} if query else {}
        super().__init__(message, status_code=500, context=context, **kwargs)

@app.exception(DatabaseError)
async def handle_database_error(request, exception):
    # Log detailed error information
    app.logger.error(f"Database error: {exception}")
    if hasattr(exception, "context") and exception.context:
        app.logger.error(f"Query: {exception.context.get('query')}")
    
    # Return appropriate response
    if app.config.DEBUG:
        return json({
            "error": "Database error",
            "message": str(exception),
            "context": getattr(exception, "context", {})
        }, status=500)
    else:
        return json({
            "error": "Internal server error",
            "message": "A database error occurred"
        }, status=500)

@app.route("/users")
async def get_users(request):
    try:
        query = "SELECT * FROM users"
        users = await execute_query(query)
        return json({"users": users})
    except Exception as e:
        raise DatabaseError("Failed to fetch users", query=query)

Blueprint Exception Handlers

from sanic import Blueprint
from sanic.response import json
from sanic.exceptions import NotFound

api_bp = Blueprint("api", url_prefix="/api")

class APIError(SanicException):
    \"\"\"API-specific error exception.\"\"\"
    
    def __init__(self, message: str, error_code: str = None, **kwargs):
        super().__init__(message, status_code=400, **kwargs)
        self.error_code = error_code

@api_bp.exception(APIError)
async def handle_api_error(request, exception):
    return json({
        "error": "API Error",
        "message": str(exception),
        "error_code": getattr(exception, "error_code", "UNKNOWN"),
        "timestamp": datetime.utcnow().isoformat()
    }, status=exception.status_code)

@api_bp.exception(NotFound)
async def handle_api_not_found(request, exception):
    return json({
        "error": "API Resource Not Found",
        "message": "The requested API endpoint does not exist",
        "path": request.path
    }, status=404)

app.blueprint(api_bp)

Install with Tessl CLI

npx tessl i tessl/pypi-sanic

docs

blueprints.md

configuration.md

core-application.md

exceptions.md

index.md

middleware-signals.md

request-response.md

server-deployment.md

websockets.md

tile.json