Errors

Error Handling

The SuiPay SDK provides comprehensive error handling with specific error types for different scenarios.

Error Types

The SDK provides the following error classes:

import {
  SuiPayError,           // Base error class
  SuiPayValidationError, // 400 - Request validation errors
  SuiPayAuthenticationError, // 401 - API key issues
  SuiPayRateLimitError,  // 429 - Rate limiting
  SuiPayServerError      // 5xx - Server-side errors
} from '@suipay/api';

Basic Error Handling

All SDK methods can throw errors. Use try-catch blocks to handle them:

try {
  const user = await client.user.get();
  console.log('User loaded successfully');
} catch (error) {
  console.error('Failed to load user:', error.message);
}

Specific Error Types

SuiPayValidationError (400)

Thrown when request validation fails:

try {
  const paymentLink = await client.paymentLinks.create({
    amount_usdc: -10, // Invalid amount
    description: 'Test payment',
    destination_type: 'INVALID_TYPE' as any
  });
} catch (error) {
  if (error instanceof SuiPayValidationError) {
    console.error('Validation error:', error.response?.error);
    // Common causes: missing fields, invalid data format, invalid values
  }
}

SuiPayAuthenticationError (401)

Thrown when API key is invalid or missing:

try {
  const user = await client.user.get();
} catch (error) {
  if (error instanceof SuiPayAuthenticationError) {
    console.error('Authentication failed - check your API key');
    // Common causes: invalid API key, missing API key, deactivated key
  }
}

SuiPayRateLimitError (429)

Thrown when rate limits are exceeded:

try {
  const user = await client.user.get();
} catch (error) {
  if (error instanceof SuiPayRateLimitError) {
    console.error('Rate limit exceeded - wait 60 seconds before retrying');
  }
}

SuiPayServerError (5xx)

Thrown when server-side errors occur:

try {
  const paymentLinks = await client.paymentLinks.list();
} catch (error) {
  if (error instanceof SuiPayServerError) {
    console.error('Server error:', error.status, error.message);
    // Server is temporarily unavailable
  }
}

Comprehensive Error Handling

Handle all error types in a single try-catch block:

import {
  SuiPayValidationError,
  SuiPayAuthenticationError,
  SuiPayRateLimitError,
  SuiPayServerError,
  SuiPayError
} from '@suipay/api';

async function handleApiCall() {
  try {
    const paymentLink = await client.paymentLinks.create({
      amount_usdc: 100,
      description: 'Test payment',
      destination_type: PaymentDestinationType.POLAR_BALANCE
    });
    
    return paymentLink;
    
  } catch (error) {
    if (error instanceof SuiPayValidationError) {
      console.error('❌ Validation Error:', error.response?.error);
      // Handle validation errors (show form errors to user)
      
    } else if (error instanceof SuiPayAuthenticationError) {
      console.error('🔑 Authentication Error: Invalid API key');
      // Handle auth errors (redirect to config page)
      
    } else if (error instanceof SuiPayRateLimitError) {
      console.error('⏳ Rate Limit Exceeded - wait 60 seconds');
      // Handle rate limiting (show retry timer)
      
    } else if (error instanceof SuiPayServerError) {
      console.error('🔧 Server Error:', error.status, error.message);
      // Handle server errors (show maintenance message)
      
    } else {
      console.error('❓ Unknown Error:', error);
      // Handle unexpected errors (network issues, etc.)
    }
    
    throw error; // Re-throw if needed
  }
}

Best Practices

1. Implement Retry Logic

async function retryableApiCall<T>(
  apiCall: () => Promise<T>,
  maxRetries: number = 3
): Promise<T> {
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      return await apiCall();
    } catch (error) {
      if (error instanceof SuiPayRateLimitError) {
        await new Promise(resolve => setTimeout(resolve, 60000));
        continue;
      }
      
      if (error instanceof SuiPayServerError && attempt < maxRetries) {
        const delay = Math.pow(2, attempt) * 1000; // Exponential backoff
        await new Promise(resolve => setTimeout(resolve, delay));
        continue;
      }
      
      // Don't retry validation or auth errors
      if (error instanceof SuiPayValidationError || 
          error instanceof SuiPayAuthenticationError) {
        throw error;
      }
      
      if (attempt === maxRetries) throw error;
    }
  }
  
  throw new Error('Max retries exceeded');
}

2. User-Friendly Messages

function getUserFriendlyMessage(error: Error): string {
  if (error instanceof SuiPayValidationError) {
    return 'Please check your input and try again';
  }
  
  if (error instanceof SuiPayAuthenticationError) {
    return 'Authentication failed. Please check your API configuration';
  }
  
  if (error instanceof SuiPayRateLimitError) {
    return 'Too many requests. Please wait 60 seconds before retrying';
  }
  
  if (error instanceof SuiPayServerError) {
    return 'Service temporarily unavailable. Please try again later';
  }
  
  return 'An unexpected error occurred. Please try again';
}

// Usage
try {
  await createPaymentLink();
} catch (error) {
  showErrorToUser(getUserFriendlyMessage(error));
}

3. Error Logging

function logError(error: Error, context: string) {
  const errorInfo = {
    context,
    timestamp: new Date().toISOString(),
    message: error.message,
    type: error.constructor.name
  };
  
  if (error instanceof SuiPayError) {
    errorInfo.status = error.status;
  }
  
  console.error('SuiPay SDK Error:', errorInfo);
  
  // Send to your logging service
  // logger.error('SuiPay SDK Error', errorInfo);
}

Error Handling Checklist

Handle specific error types with appropriate actions ✅ Implement retry logic for transient errors ✅ Log errors with sufficient context for debugging ✅ Show user-friendly messages instead of technical errors ✅ Validate input before making API calls ✅ Test error scenarios in your application

Last updated