or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

account-management.mderror-handling.mdexchange-management.mdfunding-operations.mdindex.mdmarket-data.mdorder-management.mdtrading-operations.mdutility-functions.mdwebsocket-operations.md
tile.json

error-handling.mddocs/

Error Handling

Error handling provides a comprehensive hierarchy of exception types for different failure scenarios, enabling precise error handling and recovery strategies in cryptocurrency trading applications.

Capabilities

Error Hierarchy

CCXT provides a structured error hierarchy with specific exception types for different categories of failures.

// Base error classes
class BaseError extends Error {
  constructor(message?: string);
}

class ExchangeError extends BaseError {
  constructor(message?: string);
}

class OperationFailed extends BaseError {
  constructor(message?: string);
}

// Authentication and authorization errors
class AuthenticationError extends ExchangeError {
  constructor(message?: string);
}

class PermissionDenied extends ExchangeError {
  constructor(message?: string);
}

class AccountNotEnabled extends ExchangeError {
  constructor(message?: string);
}

class AccountSuspended extends ExchangeError {
  constructor(message?: string);
}

// Request validation errors
class ArgumentsRequired extends ExchangeError {
  constructor(message?: string);
}

class BadRequest extends ExchangeError {
  constructor(message?: string);
}

class BadSymbol extends BadRequest {
  constructor(message?: string);
}

class InvalidAddress extends ExchangeError {
  constructor(message?: string);
}

class AddressPending extends ExchangeError {
  constructor(message?: string);
}

// Order and trading errors
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 ContractUnavailable extends ExchangeError {
  constructor(message?: string);
}

// Operation status errors
class OperationRejected extends ExchangeError {
  constructor(message?: string);
}

class NoChange extends ExchangeError {
  constructor(message?: string);
}

class MarginModeAlreadySet extends ExchangeError {
  constructor(message?: string);
}

class MarketClosed extends ExchangeError {
  constructor(message?: string);
}

class ManualInteractionNeeded extends ExchangeError {
  constructor(message?: string);
}

class RestrictedLocation extends ExchangeError {
  constructor(message?: string);
}

// Financial errors
class InsufficientFunds extends ExchangeError {
  constructor(message?: string);
}

// Network and connectivity errors
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 NetworkError {
  constructor(message?: string);
}

class InvalidNonce extends NetworkError {
  constructor(message?: string);
}

class ChecksumError extends NetworkError {
  constructor(message?: string);
}

class RequestTimeout extends NetworkError {
  constructor(message?: string);
}

// Response handling errors
class BadResponse extends ExchangeError {
  constructor(message?: string);
}

class NullResponse extends BadResponse {
  constructor(message?: string);
}

// Other errors
class NotSupported extends ExchangeError {
  constructor(message?: string);
}

class InvalidProxySettings extends ExchangeError {
  constructor(message?: string);
}

class ExchangeClosedByUser extends ExchangeError {
  constructor(message?: string);
}

class CancelPending extends ExchangeError {
  constructor(message?: string);
}

class UnsubscribeError extends ExchangeError {
  constructor(message?: string);
}

Error Handling Patterns

Common patterns for handling different types of errors in trading applications.

Usage Examples:

// Basic error handling
try {
  const balance = await exchange.fetchBalance();
  console.log('Balance:', balance);
} catch (error) {
  if (error instanceof ccxt.AuthenticationError) {
    console.error('Authentication failed - check API credentials');
  } else if (error instanceof ccxt.NetworkError) {
    console.error('Network error - check connection');
  } else if (error instanceof ccxt.ExchangeError) {
    console.error('Exchange error:', error.message);
  } else {
    console.error('Unexpected error:', error.message);
  }
}

// Comprehensive error handling for order creation
async function createOrderWithErrorHandling(symbol: string, side: string, amount: number, price?: number) {
  try {
    const order = await exchange.createOrder(symbol, 'limit', side, amount, price);
    console.log(`Order created successfully: ${order.id}`);
    return order;
  } catch (error) {
    if (error instanceof ccxt.InsufficientFunds) {
      console.error('Insufficient funds to place order');
      throw new Error('Not enough balance');
    } else if (error instanceof ccxt.InvalidOrder) {
      console.error('Invalid order parameters:', error.message);
      throw new Error('Order validation failed');
    } else if (error instanceof ccxt.BadSymbol) {
      console.error(`Invalid trading symbol: ${symbol}`);
      throw new Error('Invalid symbol');
    } else if (error instanceof ccxt.MarketClosed) {
      console.error(`Market ${symbol} is currently closed`);
      throw new Error('Market closed');
    } else if (error instanceof ccxt.RateLimitExceeded) {
      console.error('Rate limit exceeded, waiting before retry...');
      await new Promise(resolve => setTimeout(resolve, 1000));
      throw new Error('Rate limited');
    } else if (error instanceof ccxt.AuthenticationError) {
      console.error('Authentication failed - check API credentials');
      throw new Error('Authentication failed');
    } else if (error instanceof ccxt.PermissionDenied) {
      console.error('Permission denied - check API key permissions');
      throw new Error('Permission denied');
    } else if (error instanceof ccxt.NetworkError) {
      console.error('Network error - check connection');
      throw new Error('Network error');
    } else {
      console.error('Unexpected error:', error.message);
      throw error;
    }
  }
}

// Error handling with retry logic
async function fetchWithRetry<T>(
  operation: () => Promise<T>,
  maxRetries: number = 3,
  retryDelay: number = 1000
): Promise<T> {
  let lastError: Error;
  
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      return await operation();
    } catch (error) {
      lastError = error;
      
      // Don't retry for certain error types
      if (error instanceof ccxt.AuthenticationError ||
          error instanceof ccxt.PermissionDenied ||
          error instanceof ccxt.BadSymbol ||
          error instanceof ccxt.InvalidOrder) {
        throw error;
      }
      
      // Retry for network errors and rate limits
      if (error instanceof ccxt.NetworkError ||
          error instanceof ccxt.RateLimitExceeded ||
          error instanceof ccxt.ExchangeNotAvailable) {
        console.log(`Attempt ${attempt} failed, retrying in ${retryDelay}ms...`);
        await new Promise(resolve => setTimeout(resolve, retryDelay));
        retryDelay *= 2; // Exponential backoff
      } else {
        throw error;
      }
    }
  }
  
  throw lastError!;
}

// Usage with retry
const balanceWithRetry = await fetchWithRetry(
  () => exchange.fetchBalance(),
  3,  // Max 3 retries
  1000  // Initial 1 second delay
);

// Error handling for WebSocket operations
async function watchWithErrorHandling(symbol: string) {
  while (true) {
    try {
      const ticker = await exchange.watchTicker(symbol);
      console.log(`${symbol}: $${ticker.last}`);
    } catch (error) {
      if (error instanceof ccxt.NetworkError) {
        console.error('WebSocket network error, reconnecting...');
        await new Promise(resolve => setTimeout(resolve, 5000));
      } else if (error instanceof ccxt.UnsubscribeError) {
        console.error('Unsubscribe error, resubscribing...');
        await new Promise(resolve => setTimeout(resolve, 1000));
      } else if (error instanceof ccxt.ExchangeNotAvailable) {
        console.error('Exchange unavailable, waiting...');
        await new Promise(resolve => setTimeout(resolve, 10000));
      } else {
        console.error('Unexpected WebSocket error:', error.message);
        break;
      }
    }
  }
}

// Advanced error handling with logging and alerting
class ErrorHandler {
  private errorCounts = new Map<string, number>();
  private lastErrors = new Map<string, number>();
  
  async handleError(error: Error, context: string): Promise<boolean> {
    const errorType = error.constructor.name;
    const currentTime = Date.now();
    
    // Log error
    console.error(`[${context}] ${errorType}: ${error.message}`);
    
    // Track error frequency
    const count = this.errorCounts.get(errorType) || 0;
    this.errorCounts.set(errorType, count + 1);
    this.lastErrors.set(errorType, currentTime);
    
    // Check if we should retry
    if (this.shouldRetry(error)) {
      const delay = this.getRetryDelay(errorType, count);
      console.log(`Retrying in ${delay}ms...`);
      await new Promise(resolve => setTimeout(resolve, delay));
      return true; // Should retry
    }
    
    // Alert on critical errors
    if (this.isCriticalError(error)) {
      await this.sendAlert(error, context);
    }
    
    return false; // Should not retry
  }
  
  private shouldRetry(error: Error): boolean {
    return error instanceof ccxt.NetworkError ||
           error instanceof ccxt.RateLimitExceeded ||
           error instanceof ccxt.ExchangeNotAvailable ||
           error instanceof ccxt.RequestTimeout;
  }
  
  private getRetryDelay(errorType: string, attempts: number): number {
    const baseDelay = 1000;
    const maxDelay = 30000;
    
    // Exponential backoff with jitter
    const delay = Math.min(baseDelay * Math.pow(2, attempts), maxDelay);
    const jitter = Math.random() * 0.1 * delay;
    
    return Math.floor(delay + jitter);
  }
  
  private isCriticalError(error: Error): boolean {
    return error instanceof ccxt.AuthenticationError ||
           error instanceof ccxt.AccountSuspended ||
           error instanceof ccxt.ExchangeClosedByUser;
  }
  
  private async sendAlert(error: Error, context: string): Promise<void> {
    // Implement alerting logic (email, webhook, etc.)
    console.error(`CRITICAL ERROR in ${context}: ${error.message}`);
  }
  
  getErrorSummary(): { [errorType: string]: number } {
    return Object.fromEntries(this.errorCounts);
  }
  
  resetErrorCounts(): void {
    this.errorCounts.clear();
    this.lastErrors.clear();
  }
}

// Usage
const errorHandler = new ErrorHandler();

async function safeOperation() {
  let retryCount = 0;
  const maxRetries = 3;
  
  while (retryCount < maxRetries) {
    try {
      const result = await exchange.fetchTicker('BTC/USDT');
      return result;
    } catch (error) {
      const shouldRetry = await errorHandler.handleError(error, 'fetchTicker');
      
      if (shouldRetry && retryCount < maxRetries - 1) {
        retryCount++;
        continue;
      } else {
        throw error;
      }
    }
  }
}

// Periodic error summary
setInterval(() => {
  const summary = errorHandler.getErrorSummary();
  if (Object.keys(summary).length > 0) {
    console.log('Error summary:', summary);
  }
}, 60000); // Every minute