Error handling provides a comprehensive classification system for proper error handling and debugging in cryptocurrency trading applications. CCXT uses a hierarchical error system that allows developers to catch and handle specific error types appropriately.
Foundation error classes that all CCXT errors extend from.
/**
* Base error classes
*/
class BaseError extends Error {
constructor(message: string);
}
class ExchangeError extends BaseError {
constructor(message: string);
}
class NetworkError extends BaseError {
constructor(message: string);
}Usage Examples:
import ccxt, { BaseError, ExchangeError, NetworkError } from 'ccxt';
try {
const exchange = new ccxt.binance();
const ticker = await exchange.fetchTicker('BTC/USDT');
} catch (error) {
if (error instanceof NetworkError) {
console.log('Network issue - retry may help');
} else if (error instanceof ExchangeError) {
console.log('Exchange-specific error');
} else if (error instanceof BaseError) {
console.log('CCXT error');
} else {
console.log('Unexpected error');
}
}Errors related to API authentication and authorization.
/**
* Authentication error classes
*/
class AuthenticationError extends ExchangeError {
constructor(message: string);
}
class PermissionDenied extends AuthenticationError {
constructor(message: string);
}
class AccountNotEnabled extends PermissionDenied {
constructor(message: string);
}
class AccountSuspended extends AuthenticationError {
constructor(message: string);
}Usage Examples:
import ccxt, { AuthenticationError, PermissionDenied, AccountSuspended } from 'ccxt';
async function handleAuthenticatedRequest(exchange) {
try {
return await exchange.fetchBalance();
} catch (error) {
if (error instanceof AccountSuspended) {
console.error('Account is suspended - contact exchange support');
throw error; // Re-throw as this needs manual intervention
} else if (error instanceof AccountNotEnabled) {
console.error('Account not enabled for trading');
// Redirect user to enable trading
} else if (error instanceof PermissionDenied) {
console.error('API key lacks required permissions');
// Request user to check API key permissions
} else if (error instanceof AuthenticationError) {
console.error('Authentication failed - check API credentials');
// Prompt user to re-enter credentials
}
throw error;
}
}Errors related to malformed or invalid requests.
/**
* Request error classes
*/
class ArgumentsRequired extends ExchangeError {
constructor(message: string);
}
class BadRequest extends ExchangeError {
constructor(message: string);
}
class BadSymbol extends BadRequest {
constructor(message: string);
}
class InvalidNonce extends BadRequest {
constructor(message: string);
}Usage Examples:
import ccxt, { ArgumentsRequired, BadSymbol, InvalidNonce } from 'ccxt';
async function safeCreateOrder(exchange, symbol, type, side, amount, price) {
try {
return await exchange.createOrder(symbol, type, side, amount, price);
} catch (error) {
if (error instanceof BadSymbol) {
console.error(`Invalid trading pair: ${symbol}`);
// Show user available symbols
const markets = await exchange.loadMarkets();
const availableSymbols = Object.keys(markets);
console.log('Available symbols:', availableSymbols.slice(0, 10));
} else if (error instanceof ArgumentsRequired) {
console.error('Missing required parameters for order creation');
// Validate all required parameters are provided
} else if (error instanceof InvalidNonce) {
console.error('Invalid nonce - check system time synchronization');
// Sync system time or adjust nonce generation
}
throw error;
}
}Errors specific to trading operations and order management.
/**
* Trading error classes
*/
class InsufficientFunds extends ExchangeError {
constructor(message: string);
}
class InvalidOrder extends ExchangeError {
constructor(message: string);
}
class OrderNotFound extends ExchangeError {
constructor(message: string);
}
class OrderNotCached extends ExchangeError {
constructor(message: string);
}
class OrderImmediatelyFillable extends ExchangeError {
constructor(message: string);
}
class OrderNotFillable extends ExchangeError {
constructor(message: string);
}
class DuplicateOrderId extends ExchangeError {
constructor(message: string);
}
class CancelPending extends ExchangeError {
constructor(message: string);
}Usage Examples:
import ccxt, {
InsufficientFunds,
InvalidOrder,
OrderNotFound,
OrderImmediatelyFillable
} from 'ccxt';
async function handleTradingErrors(exchange, symbol, type, side, amount, price) {
try {
const order = await exchange.createOrder(symbol, type, side, amount, price);
return order;
} catch (error) {
if (error instanceof InsufficientFunds) {
console.error('Insufficient balance for order');
const balance = await exchange.fetchBalance();
console.log('Current balance:', balance);
// Show user their available balance
} else if (error instanceof InvalidOrder) {
console.error('Invalid order parameters');
// Validate order parameters against market limits
const market = exchange.market(symbol);
console.log('Market limits:', market.limits);
} else if (error instanceof OrderImmediatelyFillable) {
console.warn('Order would execute immediately - consider market order');
// Suggest using market order instead
} else if (error instanceof OrderNotFound) {
console.error('Order not found when trying to cancel/modify');
// Refresh order status
}
throw error;
}
}Errors related to network connectivity and communication issues.
/**
* Network error classes
*/
class NetworkError extends BaseError {
constructor(message: string);
}
class DDoSProtection extends NetworkError {
constructor(message: string);
}
class RateLimitExceeded extends NetworkError {
constructor(message: string);
}
class ExchangeNotAvailable extends NetworkError {
constructor(message: string);
}
class OnMaintenance extends ExchangeNotAvailable {
constructor(message: string);
}
class RequestTimeout extends NetworkError {
constructor(message: string);
}
class BadResponse extends NetworkError {
constructor(message: string);
}
class NullResponse extends BadResponse {
constructor(message: string);
}Usage Examples:
import ccxt, {
RateLimitExceeded,
RequestTimeout,
OnMaintenance,
DDoSProtection
} from 'ccxt';
async function robustApiCall(exchange, apiMethod, ...args) {
const maxRetries = 3;
let retryCount = 0;
while (retryCount < maxRetries) {
try {
return await exchange[apiMethod](...args);
} catch (error) {
retryCount++;
if (error instanceof RateLimitExceeded) {
console.log(`Rate limit exceeded - waiting ${exchange.rateLimit}ms`);
await new Promise(resolve => setTimeout(resolve, exchange.rateLimit));
} else if (error instanceof RequestTimeout) {
console.log(`Request timeout - retry ${retryCount}/${maxRetries}`);
await new Promise(resolve => setTimeout(resolve, 1000 * retryCount));
} else if (error instanceof OnMaintenance) {
console.log('Exchange is under maintenance');
throw error; // Don't retry maintenance errors
} else if (error instanceof DDoSProtection) {
console.log('DDoS protection active - waiting longer');
await new Promise(resolve => setTimeout(resolve, 5000 * retryCount));
} else {
throw error; // Don't retry other errors
}
if (retryCount >= maxRetries) {
console.error(`Failed after ${maxRetries} retries`);
throw error;
}
}
}
}Errors related to exchange system status and operational issues.
/**
* System error classes
*/
class OperationRejected extends ExchangeError {
constructor(message: string);
}
class NoChange extends OperationRejected {
constructor(message: string);
}
class MarginModeAlreadySet extends NoChange {
constructor(message: string);
}
class MarketClosed extends OperationRejected {
constructor(message: string);
}
class ManualInteractionNeeded extends OperationRejected {
constructor(message: string);
}
class RestrictedLocation extends OperationRejected {
constructor(message: string);
}
class ContractUnavailable extends OperationRejected {
constructor(message: string);
}Usage Examples:
import ccxt, {
MarketClosed,
RestrictedLocation,
ManualInteractionNeeded,
MarginModeAlreadySet
} from 'ccxt';
async function handleSystemErrors(exchange, operation) {
try {
return await operation();
} catch (error) {
if (error instanceof MarketClosed) {
console.error('Market is closed for trading');
const status = await exchange.fetchStatus();
console.log('Exchange status:', status);
// Wait for market to reopen
} else if (error instanceof RestrictedLocation) {
console.error('Trading restricted in your location');
// Show user location restrictions
} else if (error instanceof ManualInteractionNeeded) {
console.error('Manual intervention required');
// Direct user to exchange website
} else if (error instanceof MarginModeAlreadySet) {
console.warn('Margin mode already set to requested value');
// Continue operation as desired state is already achieved
}
throw error;
}
}Errors related to exchange configuration and settings.
/**
* Configuration error classes
*/
class NotSupported extends ExchangeError {
constructor(message: string);
}
class InvalidProxySettings extends ExchangeError {
constructor(message: string);
}
class ExchangeClosedByUser extends ExchangeError {
constructor(message: string);
}
class ChecksumError extends ExchangeError {
constructor(message: string);
}Usage Examples:
import ccxt, { NotSupported, InvalidProxySettings } from 'ccxt';
function checkExchangeSupport(exchange, feature) {
if (!exchange.has[feature]) {
throw new NotSupported(`${exchange.name} does not support ${feature}`);
}
}
async function configuredExchange(exchangeClass, config) {
try {
const exchange = new exchangeClass(config);
// Check required features
checkExchangeSupport(exchange, 'fetchTicker');
checkExchangeSupport(exchange, 'createOrder');
return exchange;
} catch (error) {
if (error instanceof NotSupported) {
console.error(`Feature not supported: ${error.message}`);
// Fallback to supported features or different exchange
} else if (error instanceof InvalidProxySettings) {
console.error('Invalid proxy configuration');
// Prompt user to correct proxy settings
}
throw error;
}
}Common patterns for comprehensive error handling in trading applications.
/**
* Error handling utility patterns
*/
interface ErrorHandler {
handleError(error: Error, context?: any): Promise<any>;
isRetryable(error: Error): boolean;
getRetryDelay(error: Error, attempt: number): number;
}Usage Examples:
import ccxt from 'ccxt';
class TradingErrorHandler {
constructor(exchange) {
this.exchange = exchange;
}
async withErrorHandling(operation, context = {}) {
const maxRetries = 3;
let attempt = 0;
while (attempt < maxRetries) {
try {
return await operation();
} catch (error) {
attempt++;
if (!this.isRetryable(error) || attempt >= maxRetries) {
await this.logError(error, context, attempt);
throw error;
}
const delay = this.getRetryDelay(error, attempt);
console.log(`Retrying in ${delay}ms (attempt ${attempt}/${maxRetries})`);
await new Promise(resolve => setTimeout(resolve, delay));
}
}
}
isRetryable(error) {
return error instanceof ccxt.NetworkError ||
error instanceof ccxt.RequestTimeout ||
error instanceof ccxt.RateLimitExceeded;
}
getRetryDelay(error, attempt) {
if (error instanceof ccxt.RateLimitExceeded) {
return this.exchange.rateLimit * attempt;
}
return 1000 * Math.pow(2, attempt); // Exponential backoff
}
async logError(error, context, attempt) {
const errorInfo = {
type: error.constructor.name,
message: error.message,
context,
attempt,
timestamp: new Date().toISOString(),
};
console.error('Trading error:', errorInfo);
// Could send to monitoring service
// await this.sendToMonitoring(errorInfo);
}
}
// Usage
const exchange = new ccxt.binance({ /* config */ });
const errorHandler = new TradingErrorHandler(exchange);
async function robustTradingOperation() {
return await errorHandler.withErrorHandling(async () => {
const balance = await exchange.fetchBalance();
return await exchange.createOrder('BTC/USDT', 'limit', 'buy', 0.001, 50000);
}, { operation: 'createOrder', symbol: 'BTC/USDT' });
}