Error Handling
Learn how to handle errors in the ZenPays SDK.
Error Types
The SDK provides specific error classes for different scenarios:
| Error Class | HTTP Status | Description |
|---|---|---|
ZenPaysError | Various | Base error class |
AuthenticationError | 401 | Invalid API key |
AuthorizationError | 403 | Insufficient permissions |
NotFoundError | 404 | Resource not found |
ValidationError | 400 | Invalid input data |
RateLimitError | 429 | Rate limit exceeded |
NetworkError | - | Network connectivity issues |
PaymentError | 402 | Payment processing failed |
ConfigurationError | - | SDK misconfiguration |
Basic Error Handling
- JavaScript
- Python
import {
AuthenticationError,
NotFoundError,
ValidationError,
ZenPaysError,
} from '@zenxdigitalholdings/zenpays'
try {
await zenpays.payments.createPaymentIntent({
amount: 1000,
currency: 'USD',
})
}
catch (error) {
if (error instanceof AuthenticationError) {
console.error('Invalid API key. Check your credentials.')
}
else if (error instanceof ValidationError) {
console.error('Validation failed:', error.message)
console.error('Fields:', error.fields)
}
else if (error instanceof NotFoundError) {
console.error('Resource not found')
}
else if (error instanceof ZenPaysError) {
console.error(`API Error [${error.code}]: ${error.message}`)
console.error('Status:', error.status)
console.error('Details:', error.details)
}
else {
throw error // Re-throw unexpected errors
}
}
from zenpays import ZenPays
from zenpays.errors import (
AuthenticationError,
NotFoundError,
ValidationError,
ZenPaysError,
)
try:
zenpays.payments.create_payment_intent({
"amount": 1000,
"currency": "USD",
})
except AuthenticationError:
print("Invalid API key. Check your credentials.")
except ValidationError as e:
print(f"Validation failed: {e}")
print(f"Fields: {e.fields}")
except NotFoundError:
print("Resource not found")
except ZenPaysError as e:
print(f"API Error [{e.code}]: {e}")
print(f"Status: {e.status}")
print(f"Details: {e.details}")
except Exception as e:
raise # Re-raise unexpected errors
Error Properties
All ZenPays errors include:
interface ZenPaysError extends Error {
message: string // Human-readable message
code?: string // Error code (e.g., 'VALIDATION_ERROR')
status?: number // HTTP status code
details?: string // Additional details
}
Rate Limiting
Handle rate limits gracefully:
- JavaScript
- Python
import { RateLimitError } from '@zenxdigitalholdings/zenpays'
async function makeRequestWithRetry(fn: () => Promise<any>, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
return await fn()
}
catch (error) {
if (error instanceof RateLimitError && i < maxRetries - 1) {
const delay = error.retryAfter ?? (2 ** i * 1000)
console.log(`Rate limited. Retrying in ${delay}ms...`)
await new Promise(resolve => setTimeout(resolve, delay))
}
else {
throw error
}
}
}
}
// Usage
const intent = await makeRequestWithRetry(() =>
zenpays.payments.createPaymentIntent({ amount: 1000, currency: 'USD' })
)
import time
from zenpays.errors import RateLimitError
def make_request_with_retry(fn, max_retries=3):
for i in range(max_retries):
try:
return fn()
except RateLimitError as e:
if i < max_retries - 1:
delay = e.retry_after if e.retry_after else (2 ** i * 1000) / 1000
print(f"Rate limited. Retrying in {delay}s...")
time.sleep(delay)
else:
raise
# Usage
intent = make_request_with_retry(
lambda: zenpays.payments.create_payment_intent({"amount": 1000, "currency": "USD"})
)
Network Errors
Handle network connectivity issues:
- JavaScript
- Python
import { NetworkError } from '@zenxdigitalholdings/zenpays'
try {
await zenpays.payments.createPaymentIntent({
amount: 1000,
currency: 'USD',
})
}
catch (error) {
if (error instanceof NetworkError) {
if (error.message === 'Request timeout') {
console.error('Request timed out. Try again later.')
}
else {
console.error('Network error. Check your connection.')
}
}
}
from zenpays.errors import NetworkError
try:
zenpays.payments.create_payment_intent({
"amount": 1000,
"currency": "USD",
})
except NetworkError as e:
if str(e) == "Request timeout":
print("Request timed out. Try again later.")
else:
print("Network error. Check your connection.")
Payment Errors
Handle payment-specific errors:
- JavaScript
- Python
import { PaymentError } from '@zenxdigitalholdings/zenpays'
try {
await zenpays.payments.confirmPayment('pi_xxx', {
customerDetails: { ... },
paymentMethodDetails: { ... },
})
} catch (error) {
if (error instanceof PaymentError) {
console.error('Payment failed:', error.message)
console.error('Intent ID:', error.paymentIntentId)
// Show user-friendly message
}
}
from zenpays.errors import PaymentError
try:
zenpays.payments.confirm_payment("pi_xxx", {
"customer_details": { ... },
"payment_method_details": { ... },
})
except PaymentError as e:
print(f"Payment failed: {e}")
print(f"Intent ID: {e.payment_intent_id}")
# Show user-friendly message
Validation Errors
Handle validation errors with field-level details:
- JavaScript
- Python
import { ValidationError } from '@zenxdigitalholdings/zenpays'
try {
await zenpays.customers.create({
email: 'invalid-email',
name: '',
})
}
catch (error) {
if (error instanceof ValidationError) {
console.error('Validation errors:')
if (error.fields) {
for (const [field, messages] of Object.entries(error.fields)) {
console.error(` ${field}: ${messages.join(', ')}`)
}
}
}
}
from zenpays.errors import ValidationError
try:
zenpays.customers.create({
"email": "invalid-email",
"name": "",
})
except ValidationError as e:
print("Validation errors:")
if e.fields:
for field, messages in e.fields.items():
print(f" {field}: {', '.join(messages)}")
Channel Limit Errors
Handle payment method amount limit violations:
- JavaScript
- Python
import { ChannelLimitError } from '@zenxdigitalholdings/zenpays'
try {
await zenpays.payments.confirmPayment('pi_xxx', {
customerDetails: { ... },
paymentMethodDetails: { ... },
})
} catch (error) {
if (error instanceof ChannelLimitError) {
const { amount, currency, paymentMethod, minimumAmount, maximumAmount } = error.limits ?? {}
console.error(`Amount ${amount} ${currency} is out of range for ${paymentMethod}`)
console.error(`Allowed range: ${minimumAmount} - ${maximumAmount} ${currency}`)
// Prompt user to adjust the amount or select a different payment method
}
}
from zenpays.errors import ChannelLimitError
try:
zenpays.payments.confirm_payment("pi_xxx", {
"customer_details": { ... },
"payment_method_details": { ... },
})
except ChannelLimitError as e:
limits = e.limits or {}
print(f"Amount {limits.get('amount')} {limits.get('currency')} is out of range for {limits.get('paymentMethod')}")
print(f"Allowed range: {limits.get('minimumAmount')} - {limits.get('maximumAmount')} {limits.get('currency')}")
# Prompt user to adjust the amount or select a different payment method
Best Practices
- Always catch errors - Don't let errors crash your application
- Use specific error types - Check for specific errors before generic ones
- Log error details - Include code, status, and details for debugging
- Show user-friendly messages - Don't expose technical details to users
- Implement retry logic - Handle transient errors automatically
- Monitor errors - Track error rates in production
Example: Complete Error Handler
- JavaScript
- Python
import {
AuthenticationError,
AuthorizationError,
ChannelLimitError,
NetworkError,
NotFoundError,
PaymentError,
RateLimitError,
ValidationError,
ZenPaysError,
} from '@zenxdigitalholdings/zenpays'
function handleZenPaysError(error: unknown): {
message: string
shouldRetry: boolean
retryDelay?: number
} {
if (error instanceof AuthenticationError) {
return { message: 'Invalid API key', shouldRetry: false }
}
if (error instanceof AuthorizationError) {
return { message: 'Access denied', shouldRetry: false }
}
if (error instanceof NotFoundError) {
return { message: 'Resource not found', shouldRetry: false }
}
if (error instanceof ValidationError) {
return { message: error.message, shouldRetry: false }
}
if (error instanceof ChannelLimitError) {
return { message: error.message, shouldRetry: false }
}
if (error instanceof RateLimitError) {
return {
message: 'Too many requests',
shouldRetry: true,
retryDelay: error.retryAfter ?? 5000,
}
}
if (error instanceof NetworkError) {
return { message: 'Network error', shouldRetry: true, retryDelay: 1000 }
}
if (error instanceof PaymentError) {
return { message: 'Payment failed', shouldRetry: false }
}
if (error instanceof ZenPaysError) {
return { message: error.message, shouldRetry: false }
}
return { message: 'An unexpected error occurred', shouldRetry: false }
}
from typing import TypedDict, Optional
from zenpays.errors import (
AuthenticationError,
AuthorizationError,
ChannelLimitError,
NetworkError,
NotFoundError,
PaymentError,
RateLimitError,
ValidationError,
ZenPaysError,
)
class ErrorResult(TypedDict):
message: str
should_retry: bool
retry_delay: Optional[int]
def handle_zenpays_error(error: Exception) -> ErrorResult:
if isinstance(error, AuthenticationError):
return {"message": "Invalid API key", "should_retry": False, "retry_delay": None}
if isinstance(error, AuthorizationError):
return {"message": "Access denied", "should_retry": False, "retry_delay": None}
if isinstance(error, NotFoundError):
return {"message": "Resource not found", "should_retry": False, "retry_delay": None}
if isinstance(error, ValidationError):
return {"message": str(error), "should_retry": False, "retry_delay": None}
if isinstance(error, ChannelLimitError):
return {"message": str(error), "should_retry": False, "retry_delay": None}
if isinstance(error, RateLimitError):
return {
"message": "Too many requests",
"should_retry": True,
"retry_delay": error.retry_after if hasattr(error, "retry_after") and error.retry_after else 5000,
}
if isinstance(error, NetworkError):
return {"message": "Network error", "should_retry": True, "retry_delay": 1000}
if isinstance(error, PaymentError):
return {"message": "Payment failed", "should_retry": False, "retry_delay": None}
if isinstance(error, ZenPaysError):
return {"message": str(error), "should_retry": False, "retry_delay": None}
return {"message": "An unexpected error occurred", "should_retry": False, "retry_delay": None}