Error Handling Reference
This section documents all the exception classes and error handling patterns in the Upstox TOTP SDK.
Exception Hierarchy
BaseException
└── Exception
└── UpstoxError (base for all SDK errors)
├── ConfigurationError
├── ValidationError
├── AuthenticationError
├── NetworkError
└── APIError
Core Exceptions
UpstoxError
- class upstox_totp.errors.UpstoxError(error_code, message, details=None)[source]
Bases:
ExceptionBase class for all Upstox API errors.
Initialize error with code, message and optional details.
Base exception class for all Upstox TOTP SDK errors.
Attributes:
message(str): Human-readable error messagedetails(dict, optional): Additional error detailssuggestions(list, optional): Troubleshooting suggestions
Example:
from upstox_totp import UpstoxTOTP, UpstoxError
try:
upx = UpstoxTOTP()
response = upx.app_token.get_access_token()
except UpstoxError as e:
print(f"Error: {e}")
print(f"Details: {e.details}")
print(f"Suggestions: {e.suggestions}")
ConfigurationError
- class upstox_totp.errors.ConfigurationError[source]
Bases:
ExceptionRaised when client configuration is invalid.
Raised when there are issues with configuration setup.
Common Causes:
Missing environment variables
Invalid credential format
Malformed configuration values
File permission issues
Example:
from upstox_totp import UpstoxTOTP, ConfigurationError
try:
# Missing required environment variables
upx = UpstoxTOTP()
except ConfigurationError as e:
print(f"Configuration error: {e}")
# Check what's missing
if "UPSTOX_USERNAME" in str(e):
print("Please set UPSTOX_USERNAME environment variable")
ValidationError
- class upstox_totp.errors.ValidationError[source]
Bases:
ExceptionRaised when input validation fails.
Raised when input validation fails.
Common Causes:
Invalid username format (not 10 digits)
Invalid PIN code format
Invalid TOTP secret format
Invalid URL format for redirect_uri
Example:
from upstox_totp import UpstoxTOTP, ValidationError
from pydantic import SecretStr
try:
upx = UpstoxTOTP(
username="invalid", # Should be 10 digits
password=SecretStr("password"),
# ... other fields
)
except ValidationError as e:
print(f"Validation error: {e}")
Error Handling Patterns
Basic Error Handling
from upstox_totp import UpstoxTOTP, UpstoxError
def safe_get_token():
try:
upx = UpstoxTOTP()
response = upx.app_token.get_access_token()
if response.success:
return response.data.access_token
else:
print(f"API returned error: {response.error}")
return None
except UpstoxError as e:
print(f"SDK error: {e}")
return None
except Exception as e:
print(f"Unexpected error: {e}")
return None
token = safe_get_token()
if token:
print("Token generated successfully")
Specific Error Handling
from upstox_totp import (
UpstoxTOTP,
ConfigurationError,
ValidationError,
UpstoxError
)
def handle_specific_errors():
try:
upx = UpstoxTOTP()
response = upx.app_token.get_access_token()
return response
except ConfigurationError as e:
print("Configuration Issue:")
print(f" Error: {e}")
print(" Solutions:")
print(" - Check your .env file")
print(" - Verify environment variables")
print(" - Run: upstox_cli check-env")
except ValidationError as e:
print("Validation Issue:")
print(f" Error: {e}")
print(" Solutions:")
print(" - Check credential formats")
print(" - Verify TOTP secret")
print(" - Ensure username is 10 digits")
except UpstoxError as e:
print("Upstox API Issue:")
print(f" Error: {e}")
if e.suggestions:
print(" Suggestions:")
for suggestion in e.suggestions:
print(f" - {suggestion}")
Retry Logic with Error Handling
import time
from upstox_totp import UpstoxTOTP, UpstoxError
def get_token_with_retry(max_retries=3, delay=5):
"""Get token with retry logic for different error types."""
for attempt in range(1, max_retries + 1):
try:
upx = UpstoxTOTP()
response = upx.app_token.get_access_token()
if response.success:
return response.data.access_token
else:
error = response.error
print(f"Attempt {attempt}: API error - {error}")
# Don't retry for certain errors
if error and "invalid_credentials" in str(error):
print("Invalid credentials - not retrying")
break
except ConfigurationError:
print("Configuration error - not retrying")
break # Don't retry configuration errors
except ValidationError:
print("Validation error - not retrying")
break # Don't retry validation errors
except UpstoxError as e:
print(f"Attempt {attempt}: Upstox error - {e}")
# Retry for network/temporary errors
except Exception as e:
print(f"Attempt {attempt}: Unexpected error - {e}")
if attempt < max_retries:
print(f"Retrying in {delay} seconds...")
time.sleep(delay)
raise Exception(f"Failed to get token after {max_retries} attempts")
Error Context and Details
Error Messages
The SDK provides detailed error messages with context:
from upstox_totp import UpstoxTOTP, ConfigurationError
try:
upx = UpstoxTOTP()
except ConfigurationError as e:
# Error messages include specific missing variables
print(e) # "Missing required environment variables: UPSTOX_USERNAME, UPSTOX_PASSWORD"
Error Details
Many errors include additional details:
from upstox_totp import UpstoxTOTP, UpstoxError
try:
upx = UpstoxTOTP()
response = upx.app_token.get_access_token()
except UpstoxError as e:
if e.details:
print("Error details:")
for key, value in e.details.items():
print(f" {key}: {value}")
Troubleshooting Suggestions
Errors often include helpful suggestions:
from upstox_totp import UpstoxTOTP, UpstoxError
try:
upx = UpstoxTOTP()
response = upx.app_token.get_access_token()
except UpstoxError as e:
print(f"Error: {e}")
if e.suggestions:
print("\nTroubleshooting suggestions:")
for i, suggestion in enumerate(e.suggestions, 1):
print(f"{i}. {suggestion}")
Common Error Scenarios
Missing Environment Variables
# Error: ConfigurationError
# Message: Missing required environment variables: UPSTOX_USERNAME
# Solution: Set the missing environment variable
import os
os.environ['UPSTOX_USERNAME'] = '9876543210'
Invalid Username Format
# Error: ValidationError
# Message: Username must be exactly 10 digits
# Solution: Use your 10-digit mobile number
from upstox_totp import UpstoxTOTP
from pydantic import SecretStr
upx = UpstoxTOTP(
username="9876543210", # Must be 10 digits
password=SecretStr("password"),
# ... other fields
)
Invalid TOTP Secret
# Error: ValidationError
# Message: Invalid TOTP secret format
# Solution: Ensure secret is base32 encoded, no spaces
# Wrong: "JBSW Y3DP EHPK 3PXP"
# Right: "JBSWY3DPEHPK3PXP"
Network Connection Issues
import requests
from upstox_totp import UpstoxTOTP, UpstoxError
try:
upx = UpstoxTOTP()
response = upx.app_token.get_access_token()
except requests.ConnectionError:
print("Network connection error")
print("Check your internet connection")
except requests.Timeout:
print("Request timeout")
print("Try again or increase timeout")
Authentication Failures
from upstox_totp import UpstoxTOTP
upx = UpstoxTOTP()
response = upx.app_token.get_access_token()
if not response.success:
error = response.error
if "invalid_credentials" in str(error):
print("Invalid username/password")
elif "invalid_totp" in str(error):
print("Invalid TOTP code")
print("Check your TOTP secret configuration")
elif "invalid_pin" in str(error):
print("Invalid PIN code")
Client ID / OAuth Issues
from upstox_totp import UpstoxTOTP
upx = UpstoxTOTP()
response = upx.app_token.get_access_token()
if not response.success:
error = response.error
if "invalid_client" in str(error):
print("Invalid client ID or secret")
print("Check your Upstox Developer App credentials")
elif "redirect_uri_mismatch" in str(error):
print("Redirect URI mismatch")
print("Ensure redirect_uri matches your app settings")
Custom Error Handling
Custom Exception Classes
from upstox_totp.errors import UpstoxError
class TokenExpiredError(UpstoxError):
"""Raised when access token has expired."""
pass
class RateLimitError(UpstoxError):
"""Raised when rate limit is exceeded."""
pass
def enhanced_get_token():
upx = UpstoxTOTP()
response = upx.app_token.get_access_token()
if not response.success:
error = response.error
if "token_expired" in str(error):
raise TokenExpiredError("Access token has expired")
elif "rate_limit" in str(error):
raise RateLimitError("Rate limit exceeded")
else:
raise UpstoxError(f"Token generation failed: {error}")
return response.data.access_token
Error Logging
import logging
from upstox_totp import UpstoxTOTP, UpstoxError
# Configure logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)
def logged_token_generation():
try:
logger.info("Starting token generation...")
upx = UpstoxTOTP()
response = upx.app_token.get_access_token()
if response.success:
logger.info("Token generated successfully")
return response.data.access_token
else:
logger.error(f"Token generation failed: {response.error}")
return None
except UpstoxError as e:
logger.error(f"Upstox error: {e}", exc_info=True)
return None
except Exception as e:
logger.error(f"Unexpected error: {e}", exc_info=True)
return None
Error Recovery Strategies
Automatic Retry
from functools import wraps
import time
def retry_on_error(max_retries=3, delay=1, backoff=2):
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
retries = 0
current_delay = delay
while retries < max_retries:
try:
return func(*args, **kwargs)
except (ConnectionError, TimeoutError) as e:
retries += 1
if retries >= max_retries:
raise e
time.sleep(current_delay)
current_delay *= backoff
return func(*args, **kwargs)
return wrapper
return decorator
@retry_on_error(max_retries=3, delay=2)
def resilient_token_generation():
upx = UpstoxTOTP()
response = upx.app_token.get_access_token()
if not response.success:
raise Exception(f"Token generation failed: {response.error}")
return response.data.access_token
Fallback Mechanisms
from upstox_totp import UpstoxTOTP, UpstoxError
def get_token_with_fallback():
"""Try multiple strategies to get a token."""
# Strategy 1: Normal generation
try:
upx = UpstoxTOTP()
response = upx.app_token.get_access_token()
if response.success:
return response.data.access_token
except Exception as e:
print(f"Strategy 1 failed: {e}")
# Strategy 2: Reset session and retry
try:
upx.reset_session()
response = upx.app_token.get_access_token()
if response.success:
return response.data.access_token
except Exception as e:
print(f"Strategy 2 failed: {e}")
# Strategy 3: New client instance
try:
upx = UpstoxTOTP()
response = upx.app_token.get_access_token()
if response.success:
return response.data.access_token
except Exception as e:
print(f"Strategy 3 failed: {e}")
raise Exception("All token generation strategies failed")
Debugging Errors
Enable Debug Mode
from upstox_totp import UpstoxTOTP
# Enable debug logging
upx = UpstoxTOTP(debug=True)
# Or via environment variable
import os
os.environ['UPSTOX_DEBUG'] = 'true'
upx = UpstoxTOTP()
Capture Request/Response
import logging
from upstox_totp import UpstoxTOTP
# Enable HTTP debugging
logging.basicConfig(level=logging.DEBUG)
logging.getLogger("urllib3").setLevel(logging.DEBUG)
upx = UpstoxTOTP(debug=True)
Inspect Session State
from upstox_totp import UpstoxTOTP
upx = UpstoxTOTP()
# Inspect session
print(f"Session cookies: {dict(upx.session.cookies)}")
print(f"Session headers: {dict(upx.session.headers)}")
try:
response = upx.app_token.get_access_token()
except Exception as e:
print(f"Error occurred: {e}")
print(f"Session state: {dict(upx.session.cookies)}")
Testing Error Conditions
Mock Errors for Testing
import pytest
from unittest.mock import patch
from upstox_totp import UpstoxTOTP, UpstoxError
def test_configuration_error():
with patch.dict('os.environ', {}, clear=True):
with pytest.raises(ConfigurationError):
UpstoxTOTP()
def test_network_error():
with patch('requests.Session.post') as mock_post:
mock_post.side_effect = ConnectionError("Network error")
upx = UpstoxTOTP()
with pytest.raises(ConnectionError):
upx.app_token.get_access_token()
Error Monitoring
Health Checks
from upstox_totp import UpstoxTOTP, ConfigurationError
def health_check():
"""Check if the SDK is properly configured."""
try:
upx = UpstoxTOTP()
return {"status": "healthy", "configuration": "valid"}
except ConfigurationError as e:
return {"status": "unhealthy", "error": str(e)}
except Exception as e:
return {"status": "error", "error": str(e)}
Metrics Collection
import time
from collections import defaultdict
from upstox_totp import UpstoxTOTP, UpstoxError
class ErrorMetrics:
def __init__(self):
self.error_counts = defaultdict(int)
self.last_errors = []
def record_error(self, error):
error_type = type(error).__name__
self.error_counts[error_type] += 1
self.last_errors.append({
'type': error_type,
'message': str(error),
'timestamp': time.time()
})
# Keep only last 100 errors
if len(self.last_errors) > 100:
self.last_errors.pop(0)
def get_summary(self):
return {
'error_counts': dict(self.error_counts),
'last_errors': self.last_errors[-10:] # Last 10 errors
}
metrics = ErrorMetrics()
def monitored_token_generation():
try:
upx = UpstoxTOTP()
response = upx.app_token.get_access_token()
return response
except Exception as e:
metrics.record_error(e)
raise
Best Practices
Always handle specific exception types before generic ones
Provide meaningful error messages to users
Log errors with sufficient context for debugging
Don’t retry configuration/validation errors - fix them instead
Use exponential backoff for retries
Monitor error rates in production
Test error conditions thoroughly
Document expected errors for API users
Clean up resources even when errors occur
Validate input early to provide better error messages
See Also
Client API Reference - Client API reference
Data Models Reference - Data models
Troubleshooting Guide - Troubleshooting guide
Configuration Guide - Configuration guide