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 Class | Status Code | Retryable | Cause |
|---|---|---|---|
RefineValidationError | 400 | No | Invalid request parameters |
RefineAuthError | 401 | No | Invalid or missing API key |
RefineForbiddenError | 403 | No | Insufficient permissions |
RefineNotFoundError | 404 | No | Resource doesn’t exist |
RefineRateLimitError | 429 | Yes | Too many requests |
RefineTimeoutError | 408, 504 | Yes | Request timed out |
RefineServerError | 500, 502, 503 | Yes | Server-side issue |
RefineNetworkError | - | Yes | Network 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 extendRefineError 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
Search
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
SDK Configuration
Configure error handling globally
Debug Plugin
Debug errors in development