Error Handling
Error Handling
Overview
The Pathao Python SDK provides comprehensive error handling with specific exception types for different error scenarios.
Exception Hierarchy
PathaoException # Base exception
├── AuthenticationError # Authentication failures
├── ValidationError # Input validation errors
├── NotFoundError # Resource not found
├── APIError # API server errors
├── NetworkError # Network/connection issues
└── ConfigurationError # Configuration problems
Import Exceptions
from pathao import (
PathaoException,
AuthenticationError,
ValidationError,
NotFoundError,
APIError,
NetworkError,
ConfigurationError
)
Authentication Errors
from pathao import PathaoClient, AuthenticationError
try:
client = PathaoClient(
client_id="invalid_id",
client_secret="invalid_secret",
username="invalid@email.com",
password="wrong_password",
environment="sandbox"
)
# This will trigger authentication
token = client.get_access_token()
except AuthenticationError as e:
print(f"❌ Authentication failed: {e}")
# Handle: Show login form, refresh credentials, etc.
Validation Errors
from pathao import ValidationError
try:
# Invalid phone number
store = client.stores.create(
store_name="Test Store",
contact_name="John Doe",
contact_number="123", # Too short
address="Test Address",
city_id=1,
zone_id=1,
area_id=1
)
except ValidationError as e:
print(f"❌ Validation error: {e}")
print(f"Field: {e.field}")
print(f"Value: {e.value}")
# Handle: Show field-specific error message
Not Found Errors
from pathao import NotFoundError
try:
# Non-existent store
store = client.stores.get(999999)
except NotFoundError as e:
print(f"❌ Resource not found: {e}")
print(f"Resource type: {e.resource_type}")
print(f"Resource ID: {e.resource_id}")
# Handle: Show "not found" message, redirect, etc.
try:
# Non-existent order
order = client.orders.get_info("INVALID-CONSIGNMENT-ID")
except NotFoundError as e:
print(f"❌ Order not found: {e}")
API Errors
from pathao import APIError
try:
order = client.orders.create(
store_id=123,
merchant_order_id="ORDER-001",
recipient_name="John Doe",
recipient_phone="01712345678",
recipient_address="Test Address",
recipient_city=1,
recipient_zone=1,
delivery_type=48,
item_type=2,
item_quantity=1,
item_weight=1.0,
amount_to_collect=100.0
)
except APIError as e:
print(f"❌ API error: {e}")
print(f"Status code: {e.status_code}")
print(f"Response data: {e.response_data}")
# Handle: Retry, show server error message, etc.
Network Errors
from pathao import NetworkError
try:
cities = client.locations.get_cities()
except NetworkError as e:
print(f"❌ Network error: {e}")
print(f"Retry count: {e.retry_count}")
# Handle: Show offline message, retry button, etc.
Configuration Errors
from pathao import ConfigurationError
try:
client = PathaoClient(
client_id="test_id",
client_secret="test_secret",
username="test@example.com",
password="test_password",
environment="invalid_env" # Invalid environment
)
except ConfigurationError as e:
print(f"❌ Configuration error: {e}")
print(f"Config key: {e.config_key}")
# Handle: Show configuration help, default values, etc.
Comprehensive Error Handling
from pathao import (
PathaoClient,
AuthenticationError,
ValidationError,
NotFoundError,
APIError,
NetworkError,
ConfigurationError,
PathaoException
)
def safe_api_call(func, *args, **kwargs):
"""Wrapper for safe API calls with comprehensive error handling."""
try:
return func(*args, **kwargs)
except AuthenticationError as e:
print(f"🔐 Authentication issue: {e}")
return {"error": "auth", "message": str(e)}
except ValidationError as e:
print(f"📝 Validation error: {e}")
return {"error": "validation", "field": e.field, "message": str(e)}
except NotFoundError as e:
print(f"🔍 Not found: {e}")
return {"error": "not_found", "resource": e.resource_type, "message": str(e)}
except APIError as e:
print(f"🌐 API error: {e}")
return {"error": "api", "status": e.status_code, "message": str(e)}
except NetworkError as e:
print(f"📡 Network error: {e}")
return {"error": "network", "retries": e.retry_count, "message": str(e)}
except ConfigurationError as e:
print(f"⚙️ Configuration error: {e}")
return {"error": "config", "key": e.config_key, "message": str(e)}
except PathaoException as e:
print(f"❌ Pathao error: {e}")
return {"error": "pathao", "message": str(e)}
except Exception as e:
print(f"💥 Unexpected error: {e}")
return {"error": "unexpected", "message": str(e)}
# Usage examples
def create_order_safely(client, order_data):
"""Create order with comprehensive error handling."""
result = safe_api_call(
client.orders.create,
**order_data
)
if isinstance(result, dict) and "error" in result:
error_type = result["error"]
if error_type == "auth":
return "Please check your credentials and try again."
elif error_type == "validation":
return f"Invalid {result['field']}: {result['message']}"
elif error_type == "not_found":
return f"{result['resource']} not found. Please check the ID."
elif error_type == "api":
return f"Server error ({result['status']}). Please try again later."
elif error_type == "network":
return "Network connection issue. Please check your internet."
else:
return f"Error: {result['message']}"
return result # Success - return the order object
# Example usage
client = PathaoClient(environment="sandbox")
order_data = {
"store_id": 123,
"merchant_order_id": "ORDER-001",
"recipient_name": "John Doe",
"recipient_phone": "01712345678",
"recipient_address": "Test Address",
"recipient_city": 1,
"recipient_zone": 1,
"delivery_type": 48,
"item_type": 2,
"item_quantity": 1,
"item_weight": 1.0,
"amount_to_collect": 100.0
}
result = create_order_safely(client, order_data)
if isinstance(result, str):
print(f"❌ {result}") # Error message
else:
print(f" Order created: {result.consignment_id}")
Retry Logic
import time
from pathao import NetworkError, APIError
def retry_api_call(func, max_retries=3, delay=1, *args, **kwargs):
"""Retry API calls with exponential backoff."""
for attempt in range(max_retries):
try:
return func(*args, **kwargs)
except (NetworkError, APIError) as e:
if attempt == max_retries - 1:
raise # Last attempt, re-raise the exception
wait_time = delay * (2 ** attempt) # Exponential backoff
print(f"⏳ Attempt {attempt + 1} failed, retrying in {wait_time}s...")
time.sleep(wait_time)
# Usage
try:
cities = retry_api_call(client.locations.get_cities)
print(f" Got {len(cities.data)} cities")
except Exception as e:
print(f"❌ All retry attempts failed: {e}")
Best Practices
- Specific Exception Handling: Catch specific exceptions rather than generic ones
- User-Friendly Messages: Convert technical errors to user-friendly messages
- Logging: Log errors for debugging while showing clean messages to users
- Retry Logic: Implement retry for network and temporary API errors
- Graceful Degradation: Provide fallback behavior when possible
- Validation First: Validate inputs before API calls to avoid server errors
- Error Context: Include relevant context (field names, resource IDs) in error messages