Error Handling

Handle API errors and exceptions gracefully

Error Handling

The SDK provides a custom DFlowApiError class for handling API errors with detailed information.

DFlowApiError

All API errors are thrown as DFlowApiError instances.

import { DFlowApiError } from 'dflow-sdk';
 
try {
  const market = await dflow.markets.getMarket('invalid-ticker');
} catch (error) {
  if (error instanceof DFlowApiError) {
    console.error(`Status: ${error.statusCode}`);
    console.error(`Message: ${error.message}`);
    console.error(`Response:`, error.response);
  }
}

Error Properties

PropertyTypeDescription
messagestringError message
statusCodenumberHTTP status code
responseunknownRaw API response body

Common Error Codes

StatusMeaningCommon Causes
400Bad RequestInvalid parameters
401UnauthorizedMissing or invalid API key
404Not FoundMarket/event doesn't exist
429Rate LimitedToo many requests
500Server ErrorAPI service issue

Handling Patterns

Basic Error Handling

import { DFlowApiError } from 'dflow-sdk';
 
async function getMarketSafely(ticker: string) {
  try {
    return await dflow.markets.getMarket(ticker);
  } catch (error) {
    if (error instanceof DFlowApiError) {
      if (error.statusCode === 404) {
        console.log(`Market ${ticker} not found`);
        return null;
      }
      throw error; // Re-throw other API errors
    }
    throw error; // Re-throw non-API errors
  }
}

Rate Limit Handling with Built-in Retry

The SDK provides built-in retry utilities with exponential backoff:

import { withRetry, createRetryable, DFlowApiError } from 'dflow-sdk';
 
// Basic usage with default options
const markets = await withRetry(() => dflow.markets.getMarkets());
 
// With custom options
const events = await withRetry(
  () => dflow.events.getEvents({ limit: 100 }),
  { maxRetries: 5, initialDelayMs: 500 }
);
 
// Custom retry condition
const quote = await withRetry(
  () => dflow.swap.getQuote(params),
  {
    shouldRetry: (error) => {
      if (error instanceof DFlowApiError) {
        return error.statusCode === 429; // Only retry rate limits
      }
      return false;
    }
  }
);

Retry Options:

OptionTypeDefaultDescription
maxRetriesnumber3Maximum retry attempts
initialDelayMsnumber1000Initial delay before first retry
maxDelayMsnumber30000Maximum delay between retries
backoffMultipliernumber2Multiplier for exponential backoff
shouldRetryfunctionRate limit + server errorsCustom retry condition

Creating Reusable Retry Functions

import { createRetryable } from 'dflow-sdk';
 
// Create a retryable version of a function
const getMarketsWithRetry = createRetryable(
  (params) => dflow.markets.getMarkets(params),
  { maxRetries: 5 }
);
 
// Use it like the original function
const markets = await getMarketsWithRetry({ limit: 50 });

Comprehensive Error Handler

import { DFlowApiError } from 'dflow-sdk';
 
function handleDFlowError(error: unknown): void {
  if (error instanceof DFlowApiError) {
    switch (error.statusCode) {
      case 400:
        console.error('Invalid request:', error.response);
        break;
      case 401:
        console.error('Authentication failed. Check your API key.');
        break;
      case 404:
        console.error('Resource not found');
        break;
      case 429:
        console.error('Rate limited. Please slow down requests.');
        break;
      case 500:
      case 502:
      case 503:
        console.error('Server error. Please try again later.');
        break;
      default:
        console.error(`API error ${error.statusCode}:`, error.message);
    }
  } else if (error instanceof Error) {
    console.error('Unexpected error:', error.message);
  } else {
    console.error('Unknown error:', error);
  }
}

WebSocket Errors

WebSocket errors are handled differently through callbacks:

// Handle connection errors
dflow.ws.onError((error) => {
  console.error('WebSocket error:', error.message);
});
 
// Handle disconnections
dflow.ws.onClose((event) => {
  console.log(`Disconnected: ${event.code} - ${event.reason}`);
});

The WebSocket client automatically attempts to reconnect on disconnection. You can configure this behavior in the client options.

Transaction Errors

For Solana transaction errors:

import { signSendAndConfirm } from 'dflow-sdk';
 
try {
  const result = await signSendAndConfirm(
    connection,
    transaction,
    keypair,
    'confirmed'
  );
  
  if (result.confirmation.value.err) {
    console.error('Transaction failed:', result.confirmation.value.err);
  }
} catch (error) {
  // Network or signing errors
  console.error('Transaction error:', error);
}

Pagination Utilities

The SDK provides utilities for handling paginated API responses:

import { paginate, collectAll, countAll, findFirst } from 'dflow-sdk';
 
// Iterate through all markets
for await (const market of paginate(
  (params) => dflow.markets.getMarkets(params),
  { getItems: (r) => r.markets }
)) {
  console.log(market.ticker, market.yesAsk);
}
 
// Collect all items into an array
const allMarkets = await collectAll(
  (params) => dflow.markets.getMarkets(params),
  { getItems: (r) => r.markets }
);
 
// Count all items without storing them
const totalMarkets = await countAll(
  (params) => dflow.markets.getMarkets(params),
  { getItems: (r) => r.markets }
);
 
// Find the first item matching a predicate
const market = await findFirst(
  (params) => dflow.markets.getMarkets(params),
  { getItems: (r) => r.markets },
  (m) => m.title.includes('Bitcoin')
);

Pagination Options:

OptionTypeDescription
getItems(response) => items[]Required. Extracts items array from response.
getCursor(response) => cursorOptional. Extracts cursor (default: response.cursor)
maxItemsnumberOptional. Maximum items to fetch in total
pageSizenumberOptional. Items per page (API default)

Best Practices

  1. Always use try-catch: Wrap API calls in try-catch blocks
  2. Check error type: Use instanceof DFlowApiError for API errors
  3. Log appropriately: Include status code and response for debugging
  4. Use built-in retry: Use withRetry for automatic exponential backoff on rate limits
  5. Graceful degradation: Provide fallbacks for non-critical failures

On this page