Skip to content

Error Handling ​

Gracefully handle API errors with the SDK's typed error hierarchy.

Description ​

The SDK provides a comprehensive error hierarchy for different types of failures. This example shows how to catch and handle specific error types appropriately.

Error Types ​

Error ClassHTTP StatusDescription
AuthenticationError401Invalid or missing API key
ValidationError400Invalid request parameters
RateLimitError429Rate limit exceeded
NetworkError5xxServer or network failures
WBAPIErrorAnyBase class for all API errors

Basic Error Handling ​

typescript
import {
  WildberriesSDK,
  AuthenticationError,
  ValidationError,
  RateLimitError,
  NetworkError,
  WBAPIError
} from 'daytona-wildberries-typescript-sdk';

const sdk = new WildberriesSDK({
  apiKey: process.env.WB_API_KEY!
});

async function safeApiCall() {
  try {
    const categories = await sdk.products.getParentAll();
    return categories;

  } catch (error) {
    if (error instanceof AuthenticationError) {
      console.error('Authentication failed:', error.message);
      console.error('Please check your API key');
      // Redirect to login or refresh token

    } else if (error instanceof RateLimitError) {
      console.error('Rate limit exceeded');
      console.error(`Retry after: ${error.retryAfter}ms`);
      // Wait and retry
      await sleep(error.retryAfter);
      return safeApiCall(); // Retry

    } else if (error instanceof ValidationError) {
      console.error('Invalid request:', error.message);
      console.error('Validation details:', error.response);
      // Fix request parameters

    } else if (error instanceof NetworkError) {
      console.error('Network error:', error.message);
      console.error('Status code:', error.statusCode);
      // Retry with exponential backoff

    } else if (error instanceof WBAPIError) {
      console.error('API error:', error.message);
      console.error('Status:', error.statusCode);
      // Generic API error handling

    } else {
      console.error('Unexpected error:', error);
      throw error;
    }
  }
}

function sleep(ms: number): Promise<void> {
  return new Promise(resolve => setTimeout(resolve, ms));
}

Error Properties ​

typescript
try {
  await sdk.products.getParentAll();
} catch (error) {
  if (error instanceof WBAPIError) {
    // Common properties for all API errors
    console.log('Error name:', error.name);       // 'RateLimitError'
    console.log('Message:', error.message);       // Human-readable message
    console.log('Status code:', error.statusCode); // HTTP status (429)
    console.log('Response:', error.response);     // Raw API response
  }

  if (error instanceof RateLimitError) {
    // Rate limit specific
    console.log('Retry after (ms):', error.retryAfter);
  }
}

Handling Promotion Module Errors ​

typescript
import {
  CampaignNotFoundError,
  InvalidBidError,
  BudgetExceededError,
  InvalidCampaignStateError
} from 'daytona-wildberries-typescript-sdk';

async function manageCampaign(campaignId: number) {
  try {
    await sdk.promotion.pauseAdv(campaignId);
  } catch (error) {
    if (error instanceof CampaignNotFoundError) {
      console.error(`Campaign ${campaignId} not found`);

    } else if (error instanceof InvalidBidError) {
      console.error('Invalid bid amount:', error.message);

    } else if (error instanceof BudgetExceededError) {
      console.error('Insufficient budget');

    } else if (error instanceof InvalidCampaignStateError) {
      console.error('Cannot pause campaign in current state');
    }
  }
}

Handling In-Store Pickup Errors ​

typescript
import {
  PickupOrderNotFoundError,
  InvalidOrderStateError,
  CustomerVerificationError,
  MetadataValidationError
} from 'daytona-wildberries-typescript-sdk';

async function processPickupOrder(orderId: number) {
  try {
    await sdk.inStorePickup.confirmOrder(orderId);
  } catch (error) {
    if (error instanceof PickupOrderNotFoundError) {
      console.error(`Order ${orderId} not found`);

    } else if (error instanceof InvalidOrderStateError) {
      console.error('Order cannot be confirmed in current state');

    } else if (error instanceof CustomerVerificationError) {
      console.error('Customer identity verification failed');

    } else if (error instanceof MetadataValidationError) {
      console.error('Invalid metadata format:', error.message);
    }
  }
}

Retry Pattern with Exponential Backoff ​

typescript
async function withRetry<T>(
  operation: () => Promise<T>,
  maxRetries = 3
): Promise<T> {
  let lastError: Error;

  for (let attempt = 0; attempt <= maxRetries; attempt++) {
    try {
      return await operation();

    } catch (error) {
      lastError = error as Error;

      // Don't retry auth or validation errors
      if (error instanceof AuthenticationError ||
          error instanceof ValidationError) {
        throw error;
      }

      // Handle rate limits
      if (error instanceof RateLimitError) {
        await sleep(error.retryAfter);
        continue;
      }

      // Exponential backoff for network errors
      if (error instanceof NetworkError && attempt < maxRetries) {
        const delay = Math.pow(2, attempt) * 1000;
        console.log(`Retry ${attempt + 1}/${maxRetries} in ${delay}ms`);
        await sleep(delay);
        continue;
      }
    }
  }

  throw lastError!;
}

// Usage
const categories = await withRetry(() =>
  sdk.products.getParentAll()
);

Error Logging Best Practices ​

typescript
async function loggedApiCall<T>(
  name: string,
  operation: () => Promise<T>
): Promise<T | null> {
  const startTime = Date.now();

  try {
    const result = await operation();
    console.log(`[${name}] Success in ${Date.now() - startTime}ms`);
    return result;

  } catch (error) {
    const duration = Date.now() - startTime;

    if (error instanceof WBAPIError) {
      console.error(`[${name}] Failed after ${duration}ms:`, {
        type: error.name,
        message: error.message,
        status: error.statusCode,
        // Don't log full response in production (may contain sensitive data)
      });
    }

    return null;
  }
}

// Usage
const balance = await loggedApiCall('getBalance', () =>
  sdk.finances.getBalance()
);

Back to Examples | Previous: Single API Call | Next: Rate Limiting

Made with ❤️ for the Wildberries developer community