Error Handling
Proper error handling is crucial for building robust applications with Gspace.
Common Error Types
Authentication Errors
pythonfrom google.auth.exceptions import RefreshError try: gspace = GSpace.from_oauth(credentials_file, scopes) except RefreshError as e: print("Authentication failed. Please re-authenticate.") except FileNotFoundError: print("Credentials file not found.")
HTTP Errors
pythonfrom googleapiclient.errors import HttpError try: event = calendar.create_event(...) except HttpError as e: if e.resp.status == 404: print("Resource not found") elif e.resp.status == 403: print("Permission denied") elif e.resp.status == 429: print("Rate limit exceeded") else: print(f"HTTP Error {e.resp.status}: {e}")
Validation Errors
pythontry: calendar.create_event( summary="Meeting", start_time=datetime.now(), end_time=datetime.now() - timedelta(hours=1) # Invalid! ) except ValueError as e: print(f"Validation error: {e}")
Error Handling Patterns
Retry Pattern
pythonfrom functools import wraps import time def retry_on_failure(max_retries=3, delay=1): def decorator(func): @wraps(func) def wrapper(*args, **kwargs): for attempt in range(max_retries): try: return func(*args, **kwargs) except HttpError as e: if attempt < max_retries - 1: if e.resp.status in [429, 500, 503]: time.sleep(delay * (2 ** attempt)) continue raise return None return wrapper return decorator @retry_on_failure(max_retries=3) def create_event_safe(*args, **kwargs): return calendar.create_event(*args, **kwargs)
Error Logging
pythonimport logging from gspace.utils.logger import get_logger logger = get_logger("gspace.app") try: event = calendar.create_event(...) except Exception as e: logger.error(f"Failed to create event: {e}", exc_info=True) # Handle error appropriately
Graceful Degradation
pythondef get_calendar_events_safe(calendar_id="primary"): try: return calendar.list_events(calendar_id=calendar_id) except HttpError as e: if e.resp.status == 403: logger.warning("No access to calendar, returning empty list") return [] elif e.resp.status == 404: logger.warning("Calendar not found") return [] else: raise
Error Categories
Recoverable Errors
These errors can be retried:
- 429 Too Many Requests - Rate limiting
- 500 Internal Server Error - Server-side errors
- 503 Service Unavailable - Temporary unavailability
Non-Recoverable Errors
These require user action:
- 401 Unauthorized - Authentication required
- 403 Forbidden - Permission denied
- 404 Not Found - Resource doesn't exist
- 400 Bad Request - Invalid request parameters
Best Practices
- Always wrap API calls - Use try-except blocks
- Log errors appropriately - Use appropriate log levels
- Provide user feedback - Inform users of errors
- Implement retries - For transient errors
- Validate input - Catch errors early
- Handle specific errors - Different errors need different handling
Error Handling Utilities
Custom Exception Classes
pythonclass GSpaceError(Exception): """Base exception for Gspace errors""" pass class AuthenticationError(GSpaceError): """Authentication related errors""" pass class QuotaExceededError(GSpaceError): """Quota limit exceeded""" pass class PermissionError(GSpaceError): """Permission denied errors""" pass
Error Handler Context Manager
pythonfrom contextlib import contextmanager @contextmanager def handle_api_errors(): try: yield except HttpError as e: if e.resp.status == 429: raise QuotaExceededError() from e elif e.resp.status == 403: raise PermissionError() from e else: raise GSpaceError(f"API error: {e}") from e # Usage with handle_api_errors(): calendar.create_event(...)
Testing Error Scenarios
pythonimport pytest from unittest.mock import patch def test_rate_limit_handling(): with patch('calendar.service') as mock_service: mock_service.side_effect = HttpError( resp=type('obj', (object,), {'status': 429})(), content=b'Rate limit exceeded' ) with pytest.raises(QuotaExceededError): calendar.create_event(...)