Proven
Asynchronous operations in modern applications introduce complex error handling challenges where failures can occur at multiple points in the execution pipeline. Traditional synchronous error handling patterns don’t adequately address async contexts where errors may be deferred, propagated across async boundaries, or lost in concurrent operations. The Async Error Handling Pattern addresses:
The Async Error Handling Pattern provides systematic error management for asynchronous operations through structured exception hierarchies, graceful degradation mechanisms, and user-friendly error reporting.
Core Principle: “Errors should be user-friendly, actionable, and provide clear recovery guidance, even in async contexts.”
Error Handling Model:
Async Request → Processing → Error Detection → Classification → User Response → Recovery Guidance
Key Components:
# Base error hierarchy for async operations
class APIError(Exception):
"""Base class for all application-specific API errors."""
def __init__(self, status_code: int, error_code: str, details: Dict[str, Any] = None):
self.status_code = status_code
self.error_code = error_code
self.details = details or {}
super().__init__(f"API Error [{error_code}]")
class AsyncOperationError(APIError):
"""Base class for async operation failures."""
def __init__(self, operation: str, details: Dict[str, Any] = None):
super().__init__(500, f"ASYNC_{operation.upper()}_FAILED", details)
self.operation = operation
class IntentClassificationFailedError(AsyncOperationError):
"""Raised when async intent classification fails."""
def __init__(self, query: str, details: Dict[str, Any] = None):
super().__init__("INTENT_CLASSIFICATION", {
"query": query,
"suggestion": "Try rephrasing your request more clearly",
**(details or {})
})
import asyncio
import logging
from typing import Optional, Dict, Any
class AsyncErrorHandler:
"""Centralized async error handling with graceful degradation."""
def __init__(self, logger: Optional[logging.Logger] = None):
self.logger = logger or logging.getLogger(__name__)
async def handle_async_operation(
self,
operation: Callable,
fallback: Optional[Callable] = None,
context: Dict[str, Any] = None
) -> Any:
"""Execute async operation with error handling and optional fallback."""
try:
result = await operation()
self.logger.info(f"Async operation succeeded: {context}")
return result
except APIError as e:
# Known API errors - provide structured response
self.logger.error(f"API error in async operation: {e.error_code}",
extra={"context": context, "details": e.details})
if fallback:
try:
fallback_result = await fallback()
self.logger.info("Fallback operation succeeded")
return fallback_result
except Exception as fallback_error:
self.logger.error(f"Fallback also failed: {fallback_error}")
raise e
except asyncio.TimeoutError:
# Timeout handling with recovery guidance
timeout_error = AsyncOperationError("TIMEOUT", {
"context": context,
"suggestion": "Try again in a few moments or check system status"
})
self.logger.error("Async operation timed out", extra={"context": context})
raise timeout_error
except Exception as e:
# Unexpected errors - wrap in structured format
unexpected_error = AsyncOperationError("UNEXPECTED", {
"original_error": str(e),
"context": context,
"suggestion": "Please report this issue to support"
})
self.logger.error(f"Unexpected error in async operation: {e}",
extra={"context": context}, exc_info=True)
raise unexpected_error
# Usage example
async def process_user_request_with_error_handling(request: Dict[str, Any]) -> Dict[str, Any]:
"""Process user request with comprehensive async error handling."""
error_handler = AsyncErrorHandler()
async def main_operation():
# Main async processing logic
intent = await classify_intent(request["query"])
response = await generate_response(intent, request)
return {"status": "success", "response": response}
async def fallback_operation():
# Fallback when main operation fails
return {
"status": "degraded",
"response": "I'm having trouble processing your request. Please try again.",
"recovery_actions": ["Rephrase your request", "Check system status", "Contact support"]
}
return await error_handler.handle_async_operation(
operation=main_operation,
fallback=fallback_operation,
context={"request_id": request.get("id"), "user": request.get("user")}
)
# Async Error Handling Configuration
error_handling:
async:
timeout_seconds: 30
max_retries: 3
retry_delay_seconds: 1
graceful_degradation:
enabled: true
fallback_timeout_seconds: 10
logging:
log_all_errors: true
include_stack_traces: true
log_recovery_attempts: true
user_messages:
include_recovery_guidance: true
technical_details: false
contact_support_threshold: 3
services/api/error_handlers.py - Central async error handlingservices/integrations/*/client.py - External API error handlingservices/orchestration/workflow_engine.py - Workflow error managementtests/patterns/test_async_error_handling.py - Pattern implementation teststests/integration/test_error_recovery.py - End-to-end error recovery testingConsolidated from multiple sources
services/ directory with domain exceptionsdocs/patterns/archive/PATTERN-INDEX-legacy.md#error-handling-patterndocs/piper-education/frameworks/emergent/error-handling-framework.mdPattern extracted and consolidated: September 15, 2025 Agent B (Cursor) - Pattern Catalog Consolidation Project