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
import {
AuthenticationError,
NotFoundError,
ValidationError,
ZenPaysError,
} from '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
}
}
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:
import { RateLimitError } from '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' })
)
Network Errors
Handle network connectivity issues:
import { NetworkError } from '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.')
}
}
}
Payment Errors
Handle payment-specific errors:
import { PaymentError } from '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
}
}
Validation Errors
Handle validation errors with field-level details:
import { ValidationError } from '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(', ')}`)
}
}
}
}
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
import {
AuthenticationError,
AuthorizationError,
NetworkError,
NotFoundError,
PaymentError,
RateLimitError,
ValidationError,
ZenPaysError,
} from '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 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 }
}