The ultra-reliable, fast ASGI+WSGI framework for building data plane APIs at scale.
—
Comprehensive HTTP exception hierarchy and error handling mechanisms for building robust APIs with proper status codes, error responses, and custom error processing.
Foundation classes for HTTP errors and status responses.
class HTTPError(Exception):
def __init__(
self,
status: str,
title: str = None,
description: str = None,
headers: dict = None,
href: str = None,
href_text: str = None,
code: int = None
):
"""
Base HTTP error class.
Args:
status: HTTP status line (e.g., '400 Bad Request')
title: Error title for response
description: Detailed error description
headers: Additional response headers
href: URI for more information
href_text: Link text for href
code: Application-specific error code
"""
def to_dict(self) -> dict:
"""
Convert error to dictionary representation.
Returns:
Error as dictionary
"""
def to_json(self) -> str:
"""
Convert error to JSON string.
Returns:
Error as JSON
"""
# Properties
status: str # HTTP status line
title: str # Error title
description: str # Error description
headers: dict # Additional headers
href: str # Information URI
href_text: str # Link text
code: int # Error code
class HTTPStatus(Exception):
def __init__(self, status: str, headers: dict = None):
"""
HTTP status response without error body.
Args:
status: HTTP status line
headers: Additional response headers
"""
# Properties
status: str # HTTP status line
headers: dict # Response headersimport falcon
class UserResource:
def on_get(self, req, resp, user_id):
user = get_user(user_id)
if not user:
raise falcon.HTTPNotFound(
title='User not found',
description=f'User with ID {user_id} does not exist'
)
resp.media = user
def on_post(self, req, resp):
try:
user_data = req.media
validate_user_data(user_data)
new_user = create_user(user_data)
resp.status = falcon.HTTP_201
resp.media = new_user
except ValidationError as e:
raise falcon.HTTPBadRequest(
title='Invalid user data',
description=str(e),
code=40001 # Application-specific code
)HTTP client error exceptions for handling invalid requests.
# 400 series errors
class HTTPBadRequest(HTTPError):
"""400 Bad Request"""
class HTTPUnauthorized(HTTPError):
"""401 Unauthorized"""
class HTTPForbidden(HTTPError):
"""403 Forbidden"""
class HTTPNotFound(HTTPError):
"""404 Not Found"""
class HTTPMethodNotAllowed(HTTPError):
"""405 Method Not Allowed"""
class HTTPNotAcceptable(HTTPError):
"""406 Not Acceptable"""
class HTTPConflict(HTTPError):
"""409 Conflict"""
class HTTPGone(HTTPError):
"""410 Gone"""
class HTTPLengthRequired(HTTPError):
"""411 Length Required"""
class HTTPPreconditionFailed(HTTPError):
"""412 Precondition Failed"""
class HTTPContentTooLarge(HTTPError):
"""413 Content Too Large"""
class HTTPPayloadTooLarge(HTTPError):
"""413 Payload Too Large (alias)"""
class HTTPUriTooLong(HTTPError):
"""414 URI Too Long"""
class HTTPUnsupportedMediaType(HTTPError):
"""415 Unsupported Media Type"""
class HTTPRangeNotSatisfiable(HTTPError):
"""416 Range Not Satisfiable"""
class HTTPUnprocessableEntity(HTTPError):
"""422 Unprocessable Entity"""
class HTTPLocked(HTTPError):
"""423 Locked"""
class HTTPFailedDependency(HTTPError):
"""424 Failed Dependency"""
class HTTPPreconditionRequired(HTTPError):
"""428 Precondition Required"""
class HTTPTooManyRequests(HTTPError):
"""429 Too Many Requests"""
class HTTPRequestHeaderFieldsTooLarge(HTTPError):
"""431 Request Header Fields Too Large"""
class HTTPUnavailableForLegalReasons(HTTPError):
"""451 Unavailable For Legal Reasons"""HTTP server error exceptions for handling internal errors.
# 500 series errors
class HTTPInternalServerError(HTTPError):
"""500 Internal Server Error"""
class HTTPNotImplemented(HTTPError):
"""501 Not Implemented"""
class HTTPBadGateway(HTTPError):
"""502 Bad Gateway"""
class HTTPServiceUnavailable(HTTPError):
"""503 Service Unavailable"""
class HTTPGatewayTimeout(HTTPError):
"""504 Gateway Timeout"""
class HTTPVersionNotSupported(HTTPError):
"""505 HTTP Version Not Supported"""
class HTTPInsufficientStorage(HTTPError):
"""507 Insufficient Storage"""
class HTTPLoopDetected(HTTPError):
"""508 Loop Detected"""
class HTTPNetworkAuthenticationRequired(HTTPError):
"""511 Network Authentication Required"""Domain-specific error classes for common web application scenarios.
# Route and routing errors
class HTTPRouteNotFound(HTTPNotFound):
"""Specific route not found error"""
# Header validation errors
class HTTPInvalidHeader(HTTPBadRequest):
"""Invalid header value error"""
class HTTPMissingHeader(HTTPBadRequest):
"""Required header missing error"""
# Parameter validation errors
class HTTPInvalidParam(HTTPBadRequest):
"""Invalid parameter value error"""
class HTTPMissingParam(HTTPBadRequest):
"""Required parameter missing error"""
# Media processing errors
class MediaNotFoundError(Exception):
"""Media handler not found"""
class MediaMalformedError(Exception):
"""Malformed media content"""
class MediaValidationError(Exception):
"""Media validation failed"""
class MultipartParseError(Exception):
"""Multipart form parsing error"""
# General application errors
class CompatibilityError(Exception):
"""Compatibility issue error"""
class HeaderNotSupported(Exception):
"""Unsupported header error"""
class InvalidMediaType(Exception):
"""Invalid media type error"""
class InvalidMediaRange(Exception):
"""Invalid media range error"""
class UnsupportedScopeError(Exception):
"""Unsupported ASGI scope error"""
class UnsupportedError(Exception):
"""General unsupported operation error"""
class OperationNotAllowed(Exception):
"""Operation not allowed error"""
class DelimiterError(Exception):
"""Delimiter parsing error"""
class PayloadTypeError(Exception):
"""Payload type error"""Error classes specific to WebSocket handling in ASGI applications.
# WebSocket errors
class WebSocketDisconnected(Exception):
"""WebSocket connection disconnected"""
class WebSocketPathNotFound(Exception):
"""WebSocket path not found"""
class WebSocketHandlerNotFound(Exception):
"""WebSocket handler not found"""
class WebSocketServerError(Exception):
"""WebSocket server error"""HTTP redirect responses for URL redirection.
class HTTPMovedPermanently(HTTPStatus):
def __init__(self, location: str):
"""
301 Moved Permanently redirect.
Args:
location: New resource location
"""
class HTTPFound(HTTPStatus):
def __init__(self, location: str):
"""
302 Found redirect.
Args:
location: Temporary resource location
"""
class HTTPSeeOther(HTTPStatus):
def __init__(self, location: str):
"""
303 See Other redirect.
Args:
location: Alternative resource location
"""
class HTTPTemporaryRedirect(HTTPStatus):
def __init__(self, location: str):
"""
307 Temporary Redirect.
Args:
location: Temporary resource location
"""
class HTTPPermanentRedirect(HTTPStatus):
def __init__(self, location: str):
"""
308 Permanent Redirect.
Args:
location: New permanent resource location
"""class RedirectResource:
def on_get(self, req, resp):
# Permanent redirect to new URL
raise falcon.HTTPMovedPermanently('/new-location')
def on_post(self, req, resp):
# Process form and redirect to success page
process_form(req.media)
raise falcon.HTTPSeeOther('/success')Advanced error handling with custom handlers and serializers.
# Error handler function signature
def error_handler(req: Request, resp: Response, ex: Exception, params: dict):
"""
Custom error handler function.
Args:
req: Request object
resp: Response object
ex: Exception that occurred
params: Route parameters
"""
# Error serializer function signature
def error_serializer(req: Request, resp: Response, exception: HTTPError) -> object:
"""
Custom error serializer function.
Args:
req: Request object
resp: Response object
exception: HTTPError to serialize
Returns:
Serializable error representation
"""import falcon
import logging
def database_error_handler(req, resp, ex, params):
"""Handle database connection errors"""
logging.error(f"Database error: {ex}")
resp.status = falcon.HTTP_503
resp.media = {
'error': 'Database temporarily unavailable',
'retry_after': 60
}
resp.set_header('Retry-After', '60')
def validation_error_handler(req, resp, ex, params):
"""Handle validation errors with detailed messages"""
resp.status = falcon.HTTP_400
resp.media = {
'error': 'Validation failed',
'details': ex.errors if hasattr(ex, 'errors') else str(ex),
'request_id': req.context.get('request_id')
}
def custom_error_serializer(req, resp, exception):
"""Custom JSON error format"""
return {
'success': False,
'error': {
'type': exception.__class__.__name__,
'title': exception.title,
'detail': exception.description,
'status': exception.status,
'timestamp': datetime.utcnow().isoformat()
}
}
# Register error handlers
app = falcon.App()
app.add_error_handler(DatabaseError, database_error_handler)
app.add_error_handler(ValidationError, validation_error_handler)
app.set_error_serializer(custom_error_serializer)# Error classes
HTTPError: type # Base HTTP error
HTTPStatus: type # Status-only response
# 4xx client errors
HTTPBadRequest: type
HTTPUnauthorized: type
HTTPForbidden: type
HTTPNotFound: type
# ... (all 4xx error classes)
# 5xx server errors
HTTPInternalServerError: type
HTTPServiceUnavailable: type
# ... (all 5xx error classes)
# Redirect classes
HTTPMovedPermanently: type
HTTPFound: type
HTTPSeeOther: type
HTTPTemporaryRedirect: type
HTTPPermanentRedirect: type
# Specialized errors
MediaNotFoundError: type
MultipartParseError: type
WebSocketDisconnected: type
# ... (all specialized error classes)Install with Tessl CLI
npx tessl i tessl/pypi-falcon