Skip to content

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.

All Voltax errors extend from the base VoltaxError class:

VoltaxError (base class)
├── VoltaxValidationError - Input validation failures
├── VoltaxGatewayError - Payment provider API errors
└── VoltaxNetworkError - Network/connectivity issues

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);
}
}

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 description
  • errors?: 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

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 provider
  • provider: 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.)

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 failure
  • originalError?: 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

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;
}
}
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;
}
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;
}
}

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."
}
}

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 them
try {
await someAxiosCall();
} catch (error) {
handleGatewayError(error, 'CustomProvider'); // Always throws
}