Error Handling
Voltax provides a comprehensive error handling system with specific error classes for different failure scenarios. This guide explains each error type and how to handle them effectively.
Error Hierarchy
Section titled “Error Hierarchy”All Voltax errors extend from the base VoltaxError class:
VoltaxError (base class)├── VoltaxValidationError - Input validation failures├── VoltaxGatewayError - Payment provider API errors└── VoltaxNetworkError - Network/connectivity issuesError Classes
Section titled “Error Classes”VoltaxError
Section titled “VoltaxError”The base error class for all Voltax-related errors.
import { VoltaxError } from '@noelzappy/voltax';
try { await voltax.paystack.initializePayment(payload);} catch (error) { if (error instanceof VoltaxError) { console.error('Voltax error:', error.message); }}VoltaxValidationError
Section titled “VoltaxValidationError”Thrown when input validation fails. This includes invalid email addresses, unsupported currencies, missing required fields, or invalid amounts.
import { VoltaxValidationError } from '@noelzappy/voltax';
try { await voltax.paystack.initializePayment({ amount: -100, // Invalid: negative amount email: 'invalid-email', // Invalid: not a valid email currency: Currency.NGN, });} catch (error) { if (error instanceof VoltaxValidationError) { console.error('Validation failed:', error.message);
// Access detailed Zod validation errors if (error.errors) { error.errors.forEach((err) => { console.error(`- ${err.path.join('.')}: ${err.message}`); }); } }}Properties:
message: Human-readable error descriptionerrors?: Array of detailed validation errors (from Zod)
Common Causes:
- Invalid or missing email address
- Negative or zero amount
- Unsupported currency
- Missing required fields (e.g., reference for Flutterwave/Hubtel)
- Invalid URL format for callback URLs
- Invalid mobile number format
VoltaxGatewayError
Section titled “VoltaxGatewayError”Thrown when the payment provider’s API returns an error response (e.g., invalid API key, transaction not found, insufficient funds).
import { VoltaxGatewayError } from '@noelzappy/voltax';
try { await voltax.paystack.verifyTransaction('invalid-reference');} catch (error) { if (error instanceof VoltaxGatewayError) { console.error('Gateway error:', error.message); console.error('Provider:', error.provider); console.error('Status code:', error.statusCode); console.error('Response data:', error.data); }}Properties:
message: Error message from the providerprovider: Name of the provider (e.g., “Paystack”, “Flutterwave”, “Hubtel”)statusCode?: HTTP status code (e.g., 400, 401, 404)data?: Raw error response from the provider
Common Causes:
- Invalid API key or credentials
- Transaction not found
- Duplicate transaction reference
- Invalid transaction state
- Account issues (suspended, etc.)
VoltaxNetworkError
Section titled “VoltaxNetworkError”Thrown when the network request fails due to connectivity issues, timeouts, or DNS errors.
import { VoltaxNetworkError } from '@noelzappy/voltax';
try { await voltax.paystack.initializePayment(payload);} catch (error) { if (error instanceof VoltaxNetworkError) { console.error('Network error:', error.message);
// Access the original error for debugging if (error.originalError) { console.error('Original error:', error.originalError); } }}Properties:
message: Description of the network failureoriginalError?: The underlying error (e.g., Axios error)
Common Causes:
- Network timeout (default: 10 seconds)
- DNS resolution failures
- Connection refused
- SSL/TLS errors
- No internet connection
Comprehensive Error Handling
Section titled “Comprehensive Error Handling”Here’s a complete example of handling all error types:
import { Voltax, Currency, PaymentStatus, VoltaxError, VoltaxValidationError, VoltaxGatewayError, VoltaxNetworkError,} from '@noelzappy/voltax';
async function processPayment(payload: InitiatePaymentDTO) { const voltax = new Voltax({ paystack: { secretKey: process.env.PAYSTACK_SECRET_KEY! }, });
try { const response = await voltax.paystack.initializePayment(payload); return { success: true, checkoutUrl: response.authorizationUrl, reference: response.reference, }; } catch (error) { // Handle validation errors (client-side issues) if (error instanceof VoltaxValidationError) { return { success: false, errorType: 'VALIDATION_ERROR', message: error.message, details: error.errors, // Suggest fixes to the user suggestion: 'Please check your input and try again.', }; }
// Handle gateway errors (provider-side issues) if (error instanceof VoltaxGatewayError) { console.error(`[${error.provider}] Gateway error:`, { statusCode: error.statusCode, data: error.data, });
// Handle specific status codes if (error.statusCode === 401) { return { success: false, errorType: 'AUTHENTICATION_ERROR', message: 'Payment service configuration error', suggestion: 'Please contact support.', }; }
return { success: false, errorType: 'GATEWAY_ERROR', message: 'Payment provider error. Please try again.', provider: error.provider, }; }
// Handle network errors (connectivity issues) if (error instanceof VoltaxNetworkError) { console.error('Network error:', error.originalError);
return { success: false, errorType: 'NETWORK_ERROR', message: 'Unable to connect to payment service.', suggestion: 'Please check your connection and try again.', retryable: true, }; }
// Handle unexpected errors if (error instanceof VoltaxError) { console.error('Unexpected Voltax error:', error); return { success: false, errorType: 'UNKNOWN_ERROR', message: 'An unexpected error occurred.', }; }
// Re-throw non-Voltax errors throw error; }}Error Handling Patterns
Section titled “Error Handling Patterns”Retry Pattern for Network Errors
Section titled “Retry Pattern for Network Errors”async function initializeWithRetry( voltax: Voltax, payload: InitiatePaymentDTO, maxRetries = 3) { let lastError: Error | null = null;
for (let attempt = 1; attempt <= maxRetries; attempt++) { try { return await voltax.paystack.initializePayment(payload); } catch (error) { if (error instanceof VoltaxNetworkError) { lastError = error; console.warn(`Attempt ${attempt} failed, retrying...`);
// Exponential backoff await new Promise(resolve => setTimeout(resolve, Math.pow(2, attempt) * 1000) ); continue; } // Don't retry non-network errors throw error; } }
throw lastError;}Provider Failover Pattern
Section titled “Provider Failover Pattern”async function initializeWithFailover( voltax: Voltax, payload: InitiatePaymentDTO) { // Try primary provider try { return await voltax.paystack.initializePayment(payload); } catch (error) { if (error instanceof VoltaxGatewayError || error instanceof VoltaxNetworkError) { console.warn('Primary provider failed, trying backup...');
// Failover to backup provider try { return await voltax.flutterwave.initializePayment({ ...payload, reference: payload.reference || `fallback-${Date.now()}`, }); } catch (backupError) { // Both providers failed throw new Error('All payment providers are currently unavailable'); } } throw error; }}Configuration Errors
Section titled “Configuration Errors”When accessing a provider that hasn’t been configured, Voltax throws a VoltaxValidationError:
const voltax = new Voltax({ paystack: { secretKey: 'sk_xxx' }, // Flutterwave not configured});
try { // This will throw because Flutterwave is not configured await voltax.flutterwave.initializePayment(payload);} catch (error) { if (error instanceof VoltaxValidationError) { console.error(error.message); // "Flutterwave configuration is missing. Please provide "flutterwave" in the Voltax constructor." }}The handleGatewayError Function
Section titled “The handleGatewayError Function”For advanced users, Voltax exports the handleGatewayError utility function used internally to process Axios errors:
import { handleGatewayError } from '@noelzappy/voltax';
// This function always throws - it transforms errors and re-throws themtry { await someAxiosCall();} catch (error) { handleGatewayError(error, 'CustomProvider'); // Always throws}Next Steps
Section titled “Next Steps”- Return to the Getting Started guide
- Learn about Initializing Payments
- Explore provider-specific guides: