Skip to main content

Overview

The SDK provides typed error classes for different failure scenarios. Some errors are retryable (network issues, rate limits), while others require code changes (validation, auth).

Error Types

Error ClassStatus CodeRetryableCause
RefineValidationError400NoInvalid request parameters
RefineAuthError401NoInvalid or missing API key
RefineForbiddenError403NoInsufficient permissions
RefineNotFoundError404NoResource doesn’t exist
RefineRateLimitError429YesToo many requests
RefineTimeoutError408, 504YesRequest timed out
RefineServerError500, 502, 503YesServer-side issue
RefineNetworkError-YesNetwork connectivity issue

Basic Error Handling

import { 
  Refine,
  RefineValidationError,
  RefineAuthError,
  RefineNotFoundError,
  RefineRateLimitError,
  RefineServerError,
  RefineNetworkError
} from '@refine-ai/sdk';

const refine = new Refine({
  apiKey: process.env.REFINE_API_KEY,
  organizationId: 'org_abc123',
  catalogId: 'cat_xyz789'
});

try {
  const results = await refine.search.text({
    query: 'summer dress',
    topK: 24
  });
} catch (error) {
  if (error instanceof RefineValidationError) {
    // Bad request - fix the parameters
    console.error('Invalid parameters:', error.message);
  } else if (error instanceof RefineAuthError) {
    // Auth issue - check API key
    console.error('Authentication failed:', error.message);
  } else if (error instanceof RefineNotFoundError) {
    // Resource not found
    console.error('Not found:', error.message);
  } else if (error instanceof RefineRateLimitError) {
    // Rate limited - wait and retry
    console.error(`Rate limited. Retry after ${error.retryAfter}ms`);
  } else if (error instanceof RefineServerError) {
    // Server error - retry with backoff
    console.error('Server error:', error.message);
  } else if (error instanceof RefineNetworkError) {
    // Network issue - check connectivity
    console.error('Network error:', error.message);
  } else {
    // Unknown error
    throw error;
  }
}

Error Properties

All Refine errors extend RefineError and include:
interface RefineError extends Error {
  name: string;          // Error class name
  message: string;       // Human-readable message
  statusCode?: number;   // HTTP status code
  retryable: boolean;    // Whether retry might succeed
  retryAfter?: number;   // Suggested retry delay (ms)
  requestId?: string;    // Request ID for support
}

Retry Strategies

For retryable errors, implement exponential backoff:
async function searchWithRetry(
  query: string,
  maxRetries: number = 3
): Promise<SearchResponse> {
  let lastError: Error;
  
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    try {
      return await refine.search.text({ query, topK: 24 });
    } catch (error) {
      lastError = error;
      
      if (error instanceof RefineRateLimitError) {
        // Use server-provided retry delay
        await sleep(error.retryAfter || 1000);
      } else if (
        error instanceof RefineServerError ||
        error instanceof RefineTimeoutError ||
        error instanceof RefineNetworkError
      ) {
        // Exponential backoff
        await sleep(Math.pow(2, attempt) * 1000);
      } else {
        // Non-retryable error
        throw error;
      }
    }
  }
  
  throw lastError;
}

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

Global Error Handler

Set a global error handler in configuration:
const refine = new Refine({
  apiKey: process.env.REFINE_API_KEY,
  organizationId: 'org_abc123',
  catalogId: 'cat_xyz789',
  onError: (error) => {
    // Log to error tracking service
    errorTracker.capture(error, {
      requestId: error.requestId,
      statusCode: error.statusCode
    });
    
    // Show user-friendly message
    if (error.retryable) {
      showNotification('Temporary issue. Please try again.');
    } else {
      showNotification('Something went wrong. Please contact support.');
    }
  }
});

Error Handling by Feature

async function performSearch(query: string) {
  try {
    return await refine.search.text({ query, topK: 24 });
  } catch (error) {
    if (error instanceof RefineValidationError) {
      // Query too short, invalid filters, etc.
      return { results: [], error: 'Invalid search query' };
    }
    if (error.retryable) {
      // Show loading state and retry
      return await searchWithRetry(query);
    }
    // Non-retryable error
    return { results: [], error: 'Search unavailable' };
  }
}

Recommendations

async function getSimilarItems(productId: string) {
  try {
    return await refine.recs.similarItems({
      anchorId: productId,
      topK: 8
    });
  } catch (error) {
    if (error instanceof RefineNotFoundError) {
      // Product not in catalog - fall back to popular items
      return await refine.recs.forVisitor({
        configId: 'popular',
        topK: 8
      });
    }
    if (error.retryable) {
      // Retry once
      await sleep(1000);
      return await refine.recs.similarItems({
        anchorId: productId,
        topK: 8
      });
    }
    // Return empty recommendations
    return { results: [] };
  }
}

Event Tracking

Event tracking is designed to be fire-and-forget, but you can handle errors:
try {
  refine.events.trackPurchase({
    orderId: 'order_123',
    value: 99.99,
    currency: 'USD',
    items: [{ itemId: 'sku_001', quantity: 1, unitPrice: 99.99 }]
  });
} catch (error) {
  // Events are queued, so errors here are rare
  console.error('Failed to queue event:', error);
}

// Flush errors
try {
  await refine.events.flush();
} catch (error) {
  if (error instanceof RefineNetworkError) {
    // Events will be retried automatically
    console.warn('Events queued for retry');
  }
}

User-Facing Error Messages

Map errors to user-friendly messages:
function getUserMessage(error: RefineError): string {
  if (error instanceof RefineValidationError) {
    return 'Please check your search query and try again.';
  }
  if (error instanceof RefineRateLimitError) {
    return 'Too many requests. Please wait a moment.';
  }
  if (error instanceof RefineNetworkError) {
    return 'Connection issue. Check your internet and try again.';
  }
  if (error.retryable) {
    return 'Temporary issue. Please try again.';
  }
  return 'Something went wrong. Please try again later.';
}

Debugging Errors

Enable debug mode for detailed error information:
const refine = new Refine({
  apiKey: process.env.REFINE_API_KEY,
  organizationId: 'org_abc123',
  catalogId: 'cat_xyz789',
  debug: true
});

// Errors will include:
// - Full request/response details
// - Request ID for support
// - Stack trace

Error Monitoring Integration

Integrate with error monitoring services:
import * as Sentry from '@sentry/browser';

const refine = new Refine({
  apiKey: process.env.REFINE_API_KEY,
  organizationId: 'org_abc123',
  catalogId: 'cat_xyz789',
  onError: (error) => {
    Sentry.captureException(error, {
      tags: {
        refine_error: error.name,
        retryable: error.retryable,
        status_code: error.statusCode
      },
      extra: {
        request_id: error.requestId
      }
    });
  }
});

Handling Specific Scenarios

Rate Limiting

import { RefineRateLimitError } from '@refine-ai/sdk';

async function handleRateLimit<T>(
  operation: () => Promise<T>
): Promise<T> {
  try {
    return await operation();
  } catch (error) {
    if (error instanceof RefineRateLimitError) {
      // Show user feedback
      showNotification(`Please wait ${Math.ceil(error.retryAfter / 1000)} seconds`);
      
      // Wait and retry once
      await sleep(error.retryAfter);
      return await operation();
    }
    throw error;
  }
}

// Usage
const results = await handleRateLimit(() => 
  refine.search.text({ query: 'shoes', topK: 24 })
);

Network Offline

import { RefineNetworkError } from '@refine-ai/sdk';

async function searchWithOfflineSupport(query: string) {
  try {
    return await refine.search.text({ query, topK: 24 });
  } catch (error) {
    if (error instanceof RefineNetworkError) {
      // Check if actually offline
      if (!navigator.onLine) {
        showNotification('You appear to be offline');
        return getCachedResults(query);
      }
      // Online but network error - retry
      await sleep(2000);
      return await refine.search.text({ query, topK: 24 });
    }
    throw error;
  }
}

Next Steps