Spaces:
Sleeping
Sleeping
Claude Code - Backend Implementation Specialist
Deploy AI-powered Todo application to Hugging Face Spaces
f2b5c2a | """ | |
| Error formatter for user-friendly error messages. | |
| This module maps technical errors to safe, user-friendly messages | |
| without exposing internal system details. | |
| """ | |
| import logging | |
| from typing import Dict, Any, Optional | |
| from enum import Enum | |
| logger = logging.getLogger(__name__) | |
| class ErrorSeverity(str, Enum): | |
| """Error severity levels.""" | |
| LOW = "low" | |
| MEDIUM = "medium" | |
| HIGH = "high" | |
| CRITICAL = "critical" | |
| class ErrorCategory(str, Enum): | |
| """Error categories for classification.""" | |
| VALIDATION = "validation" | |
| AUTHENTICATION = "authentication" | |
| AUTHORIZATION = "authorization" | |
| NOT_FOUND = "not_found" | |
| DATABASE = "database" | |
| EXTERNAL_API = "external_api" | |
| INTERNAL = "internal" | |
| class ErrorFormatter: | |
| """ | |
| Formats errors into user-friendly messages. | |
| This formatter ensures that: | |
| - Users never see stack traces or technical details | |
| - Error messages are actionable and helpful | |
| - Internal details are logged for debugging | |
| - Severity is properly categorized | |
| """ | |
| # Map error codes to user-friendly messages | |
| ERROR_MESSAGES = { | |
| # Validation errors | |
| "INVALID_TITLE": "Task title cannot be empty. Please provide a title for your task.", | |
| "INVALID_FILTER": "Invalid filter. Please use 'all', 'pending', or 'completed'.", | |
| "MISSING_IDENTIFIER": "Please specify either a task ID or task title.", | |
| "NO_UPDATES": "Please specify what you'd like to update (title or description).", | |
| "VALIDATION_ERROR": "The information provided is invalid. Please check and try again.", | |
| # Task errors | |
| "TASK_NOT_FOUND": "Task not found. Use 'show tasks' to see your list.", | |
| "AMBIGUOUS_MATCH": "Multiple tasks match that description. Please be more specific or use the task ID.", | |
| "ALREADY_COMPLETED": "This task is already marked as complete.", | |
| # Database errors | |
| "DATABASE_ERROR": "We're having trouble saving your changes. Please try again in a moment.", | |
| "CONNECTION_ERROR": "Unable to connect to the database. Please try again later.", | |
| # AI/API errors | |
| "AI_SERVICE_ERROR": "The AI service is temporarily unavailable. Please try again.", | |
| "RATE_LIMIT_EXCEEDED": "Too many requests. Please wait a moment and try again.", | |
| "TIMEOUT_ERROR": "The request took too long. Please try again.", | |
| # Authentication/Authorization errors | |
| "UNAUTHORIZED": "You need to be logged in to do that.", | |
| "FORBIDDEN": "You don't have permission to access that resource.", | |
| "INVALID_TOKEN": "Your session has expired. Please log in again.", | |
| # Generic errors | |
| "INTERNAL_ERROR": "Something went wrong on our end. We're looking into it.", | |
| "UNKNOWN_ERROR": "An unexpected error occurred. Please try again." | |
| } | |
| def format_error( | |
| cls, | |
| error_code: str, | |
| error_message: Optional[str] = None, | |
| severity: ErrorSeverity = ErrorSeverity.MEDIUM, | |
| category: ErrorCategory = ErrorCategory.INTERNAL, | |
| internal_details: Optional[str] = None | |
| ) -> Dict[str, Any]: | |
| """ | |
| Format an error into a user-friendly response. | |
| Args: | |
| error_code: Error code for classification | |
| error_message: Optional custom error message | |
| severity: Error severity level | |
| category: Error category | |
| internal_details: Internal details for logging (not shown to user) | |
| Returns: | |
| Formatted error dictionary | |
| """ | |
| # Get user-friendly message | |
| user_message = error_message or cls.ERROR_MESSAGES.get( | |
| error_code, | |
| cls.ERROR_MESSAGES["UNKNOWN_ERROR"] | |
| ) | |
| # Log internal details | |
| if internal_details: | |
| log_level = cls._get_log_level(severity) | |
| logger.log( | |
| log_level, | |
| f"Error [{error_code}] - Category: {category}, Severity: {severity} - {internal_details}" | |
| ) | |
| return { | |
| "success": False, | |
| "error": user_message, | |
| "error_code": error_code, | |
| "severity": severity.value, | |
| "category": category.value | |
| } | |
| def format_validation_error(cls, message: str, field: Optional[str] = None) -> Dict[str, Any]: | |
| """Format a validation error.""" | |
| return cls.format_error( | |
| error_code="VALIDATION_ERROR", | |
| error_message=message, | |
| severity=ErrorSeverity.LOW, | |
| category=ErrorCategory.VALIDATION, | |
| internal_details=f"Validation failed for field: {field}" if field else None | |
| ) | |
| def format_database_error(cls, exception: Exception) -> Dict[str, Any]: | |
| """Format a database error.""" | |
| return cls.format_error( | |
| error_code="DATABASE_ERROR", | |
| severity=ErrorSeverity.HIGH, | |
| category=ErrorCategory.DATABASE, | |
| internal_details=str(exception) | |
| ) | |
| def format_ai_service_error(cls, exception: Exception) -> Dict[str, Any]: | |
| """Format an AI service error.""" | |
| return cls.format_error( | |
| error_code="AI_SERVICE_ERROR", | |
| severity=ErrorSeverity.MEDIUM, | |
| category=ErrorCategory.EXTERNAL_API, | |
| internal_details=str(exception) | |
| ) | |
| def format_authentication_error(cls) -> Dict[str, Any]: | |
| """Format an authentication error.""" | |
| return cls.format_error( | |
| error_code="UNAUTHORIZED", | |
| severity=ErrorSeverity.MEDIUM, | |
| category=ErrorCategory.AUTHENTICATION | |
| ) | |
| def format_authorization_error(cls) -> Dict[str, Any]: | |
| """Format an authorization error.""" | |
| return cls.format_error( | |
| error_code="FORBIDDEN", | |
| severity=ErrorSeverity.MEDIUM, | |
| category=ErrorCategory.AUTHORIZATION | |
| ) | |
| def _get_log_level(severity: ErrorSeverity) -> int: | |
| """Map severity to logging level.""" | |
| severity_map = { | |
| ErrorSeverity.LOW: logging.INFO, | |
| ErrorSeverity.MEDIUM: logging.WARNING, | |
| ErrorSeverity.HIGH: logging.ERROR, | |
| ErrorSeverity.CRITICAL: logging.CRITICAL | |
| } | |
| return severity_map.get(severity, logging.ERROR) | |
| # Singleton instance | |
| error_formatter = ErrorFormatter() | |