CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-pyfcm

Python client for FCM - Firebase Cloud Messaging (Android, iOS and Web)

Pending
Overview
Eval results
Files

error-handling.mddocs/

Error Handling

PyFCM provides comprehensive exception handling for various Firebase Cloud Messaging error conditions. The error system helps developers identify and respond appropriately to different failure scenarios including authentication issues, server problems, and data validation errors.

Capabilities

Base Exception Class

Root exception class for all PyFCM-specific errors, providing a common base for exception handling.

class FCMError(Exception):
    """
    Base exception class for all PyFCM errors.
    
    All PyFCM-specific exceptions inherit from this class,
    enabling broad exception handling with `except FCMError`.
    """

Authentication Errors

Errors related to API authentication, credentials, and authorization issues.

class AuthenticationError(FCMError):
    """
    Raised when API key not found or authentication fails.
    
    Common causes:
    - Invalid or missing service account file
    - Incorrect project ID
    - Expired or invalid OAuth2 credentials
    - Missing required authentication parameters
    
    Resolution:
    - Verify service account file path and contents
    - Ensure project ID matches the service account
    - Check credential scopes and permissions
    """

Registration Token Errors

Errors related to invalid, expired, or unregistered device tokens.

class FCMNotRegisteredError(FCMError):
    """
    Raised when device token is invalid, missing, or unregistered.
    
    Common causes:
    - App uninstalled from device
    - App data cleared
    - Token expired or rotated
    - Invalid token format
    
    Resolution:
    - Remove token from database
    - Request new token from client app
    - Implement token refresh logic
    """

Sender Authorization Errors

Errors when the authenticated sender doesn't match the token's registered sender.

class FCMSenderIdMismatchError(FCMError):
    """
    Raised when authenticated sender differs from token's registered sender.
    
    Common causes:
    - Using wrong service account for token
    - Token registered with different Firebase project
    - Cross-project token usage
    
    Resolution:
    - Verify service account matches token's project
    - Use correct credentials for target project
    - Re-register token with current project
    """

Server Errors

Errors indicating Firebase Cloud Messaging service issues or connectivity problems.

class FCMServerError(FCMError):
    """
    Raised for internal server errors or service timeouts.
    
    Common causes:
    - FCM service temporarily unavailable
    - Network connectivity issues
    - Server overload or maintenance
    - Request timeout
    
    Resolution:
    - Implement retry logic with exponential backoff
    - Check FCM service status
    - Verify network connectivity
    - Increase timeout values if needed
    """

Data Validation Errors

Errors related to incorrect data format, structure, or validation failures.

class InvalidDataError(FCMError):
    """
    Raised when input data is incorrectly formatted or structured.
    
    Common causes:
    - Invalid JSON in configuration objects
    - Wrong data types for parameters
    - Missing required fields
    - Data exceeding size limits (4KB payload limit)
    
    Resolution:
    - Validate input data structure
    - Check parameter types and formats
    - Ensure data payload within size limits
    - Review FCM API documentation for requirements
    """

Internal Package Errors

Errors indicating internal PyFCM processing issues.

class InternalPackageError(FCMError):
    """
    Raised for JSON parsing errors or internal package issues.
    
    This error indicates a problem within PyFCM itself,
    typically related to response parsing or internal state.
    
    Resolution:
    - Report issue to PyFCM maintainers
    - Include error details and reproduction steps
    - Check for known issues in project repository
    """

Retry Control Exceptions

Exceptions for handling FCM retry-after responses and flow control.

class RetryAfterException(Exception):
    """
    Raised when FCM returns Retry-After header requiring delay.
    
    Attributes:
    - delay (int): Seconds to wait before retrying
    
    Note: This exception must be handled by external logic
    as it requires application-specific retry strategies.
    """
    
    def __init__(self, delay):
        """
        Initialize with retry delay.
        
        Parameters:
        - delay (int): Seconds to wait before retry
        """
        self.delay = delay

Usage Examples

Basic Error Handling

from pyfcm import FCMNotification
from pyfcm.errors import (
    AuthenticationError,
    FCMNotRegisteredError,
    FCMServerError,
    InvalidDataError
)

fcm = FCMNotification(
    service_account_file="service-account.json",
    project_id="your-project-id"
)

try:
    result = fcm.notify(
        fcm_token="device_token",
        notification_title="Test Message",
        notification_body="Testing error handling"
    )
    print(f"Message sent successfully: {result['name']}")
    
except AuthenticationError as e:
    print(f"Authentication failed: {e}")
    # Handle credential issues
    
except FCMNotRegisteredError as e:
    print(f"Invalid token: {e}")
    # Remove token from database
    
except FCMServerError as e:
    print(f"FCM service error: {e}")
    # Implement retry logic
    
except InvalidDataError as e:
    print(f"Data validation error: {e}")
    # Fix data format issues

Comprehensive Error Handling

from pyfcm.errors import FCMError
import time
import logging

def send_with_retry(fcm, **kwargs):
    """Send notification with retry logic and comprehensive error handling"""
    max_attempts = 3
    base_delay = 1
    
    for attempt in range(max_attempts):
        try:
            return fcm.notify(**kwargs)
            
        except AuthenticationError as e:
            logging.error(f"Authentication error (not retryable): {e}")
            raise  # Don't retry authentication errors
            
        except FCMNotRegisteredError as e:
            logging.warning(f"Token unregistered: {e}")
            # Remove token from database
            return None
            
        except FCMServerError as e:
            if attempt < max_attempts - 1:
                delay = base_delay * (2 ** attempt)
                logging.warning(f"Server error, retrying in {delay}s: {e}")
                time.sleep(delay)
                continue
            else:
                logging.error(f"Server error after {max_attempts} attempts: {e}")
                raise
                
        except InvalidDataError as e:
            logging.error(f"Data validation error (not retryable): {e}")
            raise  # Don't retry data errors
            
        except FCMError as e:
            logging.error(f"Unknown FCM error: {e}")
            raise

Batch Operation Error Handling

def handle_batch_responses(responses, tokens):
    """Process batch operation responses and handle errors"""
    successful = []
    failed_tokens = []
    
    for i, (response, token) in enumerate(zip(responses, tokens)):
        try:
            if 'error' in response:
                error_code = response['error'].get('status', 'UNKNOWN')
                
                if error_code == 'NOT_FOUND':
                    # Token no longer valid
                    failed_tokens.append(token)
                    logging.warning(f"Token {i} invalid, removing: {token}")
                    
                elif error_code == 'INVALID_ARGUMENT':
                    logging.error(f"Token {i} data error: {response['error']}")
                    
                else:
                    logging.error(f"Token {i} unknown error: {response['error']}")
            else:
                successful.append(response['name'])
                
        except KeyError as e:
            logging.error(f"Unexpected response format for token {i}: {e}")
    
    return successful, failed_tokens

Token Management with Error Handling

class TokenManager:
    """Manage FCM tokens with automatic error handling and cleanup"""
    
    def __init__(self, fcm_client):
        self.fcm = fcm_client
        self.invalid_tokens = set()
    
    def send_to_token(self, token, **kwargs):
        """Send message with automatic token validation"""
        if token in self.invalid_tokens:
            return None
            
        try:
            return self.fcm.notify(fcm_token=token, **kwargs)
            
        except FCMNotRegisteredError:
            # Mark token as invalid and remove from storage
            self.invalid_tokens.add(token)
            self.remove_token_from_database(token)
            return None
            
        except FCMSenderIdMismatchError:
            # Token belongs to different project
            self.invalid_tokens.add(token)
            return None
    
    def remove_token_from_database(self, token):
        """Remove invalid token from persistent storage"""
        # Implementation depends on storage system
        pass

Error Response Codes

PyFCM maps HTTP status codes to appropriate exceptions:

  • 200: Success
  • 400: InvalidDataError - Malformed request
  • 401: AuthenticationError - Invalid credentials
  • 403: FCMSenderIdMismatchError - Sender not authorized for token
  • 404: FCMNotRegisteredError - Token not found/registered
  • 500+: FCMServerError - Server errors and timeouts

Best Practices

Retry Strategies

  • Don't retry: AuthenticationError, InvalidDataError, FCMSenderIdMismatchError
  • Retry with backoff: FCMServerError
  • Remove and don't retry: FCMNotRegisteredError

Logging and Monitoring

import logging

# Configure logging for error tracking
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)

# Log all FCM operations for monitoring
logger = logging.getLogger('pyfcm_operations')

Token Lifecycle Management

  1. Registration: Store tokens securely with metadata
  2. Validation: Handle registration errors during messaging
  3. Refresh: Implement client-side token refresh logic
  4. Cleanup: Remove invalid tokens promptly

Install with Tessl CLI

npx tessl i tessl/pypi-pyfcm

docs

async-operations.md

core-messaging.md

error-handling.md

index.md

tile.json