Skip to main content
The SDK throws standard JavaScript errors when requests fail. This guide covers common error scenarios and how to handle them.

Basic Error Handling

Wrap API calls in try-catch blocks:
try {
  const agent = await client.agents.get(agentId);
} catch (error) {
  console.error('Failed to get agent:', error.message);
}

Error Types

Authentication Errors (401)

When your token is invalid or expired:
try {
  const agents = await client.agents.list();
} catch (error) {
  if (error.message === 'Unauthorized') {
    // Token is invalid or expired
    client.clearAuthToken();
    redirectToLogin();
  }
}
The onAuthError callback is also triggered:
const client = createWassistClient({
  baseUrl: 'https://api.wassist.app/api/v1/',
  authToken: token,
  onAuthError: () => {
    // Automatically called on 401 responses
    localStorage.removeItem('token');
    window.location.href = '/login';
  },
});

Not Found Errors (404)

When a resource doesn’t exist:
try {
  const agent = await client.agents.get('invalid-uuid');
} catch (error) {
  if (error.message.includes('404') || error.message.includes('Not found')) {
    console.log('Agent not found');
  }
}

Validation Errors (400)

When your request data is invalid:
try {
  await client.agents.create({
    name: '', // Invalid: empty name
  });
} catch (error) {
  // Error message will describe the validation issue
  console.log('Validation error:', error.message);
}

Server Errors (500)

When something goes wrong on the server:
try {
  await client.agents.list();
} catch (error) {
  if (error.message.includes('500') || error.message === 'Unknown error') {
    // Retry or show user-friendly message
    console.log('Server error, please try again');
  }
}

Creating a Robust Error Handler

interface ApiError {
  type: 'auth' | 'notFound' | 'validation' | 'server' | 'network';
  message: string;
  original: Error;
}

function handleApiError(error: unknown): ApiError {
  if (!(error instanceof Error)) {
    return {
      type: 'server',
      message: 'An unexpected error occurred',
      original: new Error(String(error)),
    };
  }
  
  const message = error.message.toLowerCase();
  
  if (message === 'unauthorized') {
    return { type: 'auth', message: 'Please log in again', original: error };
  }
  
  if (message.includes('not found') || message.includes('404')) {
    return { type: 'notFound', message: 'Resource not found', original: error };
  }
  
  if (message.includes('failed to fetch') || message.includes('network')) {
    return { type: 'network', message: 'Network error, check your connection', original: error };
  }
  
  if (message.includes('500') || message.includes('server')) {
    return { type: 'server', message: 'Server error, please try again', original: error };
  }
  
  return { type: 'validation', message: error.message, original: error };
}

// Usage
try {
  await client.agents.update(agentId, data);
} catch (error) {
  const apiError = handleApiError(error);
  
  switch (apiError.type) {
    case 'auth':
      redirectToLogin();
      break;
    case 'notFound':
      showNotification('This agent no longer exists');
      break;
    case 'validation':
      showValidationError(apiError.message);
      break;
    case 'network':
      showRetryDialog();
      break;
    case 'server':
      showErrorPage();
      break;
  }
}

Retry Logic

For transient failures, implement retry logic:
async function withRetry<T>(
  fn: () => Promise<T>,
  options: { maxRetries?: number; delay?: number } = {}
): Promise<T> {
  const { maxRetries = 3, delay = 1000 } = options;
  
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      return await fn();
    } catch (error) {
      const isRetryable = 
        error instanceof Error && 
        (error.message.includes('500') || 
         error.message.includes('network') ||
         error.message.includes('timeout'));
      
      if (!isRetryable || attempt === maxRetries) {
        throw error;
      }
      
      console.log(`Attempt ${attempt} failed, retrying in ${delay}ms...`);
      await new Promise(resolve => setTimeout(resolve, delay * attempt));
    }
  }
  
  throw new Error('Max retries exceeded');
}

// Usage
const agent = await withRetry(() => client.agents.get(agentId));

React Error Handling

With React Query or SWR:
import { useQuery } from '@tanstack/react-query';

function useAgent(agentId: string) {
  return useQuery({
    queryKey: ['agent', agentId],
    queryFn: () => client.agents.get(agentId),
    retry: (failureCount, error) => {
      // Don't retry auth errors
      if (error.message === 'Unauthorized') return false;
      // Retry up to 3 times for other errors
      return failureCount < 3;
    },
    onError: (error) => {
      if (error.message === 'Unauthorized') {
        logout();
      }
    },
  });
}

function AgentComponent({ agentId }: { agentId: string }) {
  const { data: agent, error, isLoading } = useAgent(agentId);
  
  if (isLoading) return <Loading />;
  if (error) return <ErrorDisplay error={error} />;
  
  return <AgentDetails agent={agent!} />;
}

Error Boundaries (React)

Catch errors at the component level:
import { ErrorBoundary } from 'react-error-boundary';

function ErrorFallback({ error, resetErrorBoundary }) {
  return (
    <div>
      <h2>Something went wrong</h2>
      <p>{error.message}</p>
      <button onClick={resetErrorBoundary}>Try again</button>
    </div>
  );
}

function App() {
  return (
    <ErrorBoundary FallbackComponent={ErrorFallback}>
      <AgentList />
    </ErrorBoundary>
  );
}

Logging Errors

For production applications, log errors for debugging:
async function apiCall<T>(fn: () => Promise<T>): Promise<T> {
  try {
    return await fn();
  } catch (error) {
    // Log to your error tracking service
    console.error('API Error:', {
      message: error instanceof Error ? error.message : 'Unknown error',
      stack: error instanceof Error ? error.stack : undefined,
      timestamp: new Date().toISOString(),
    });
    
    // Re-throw for handling
    throw error;
  }
}

// Usage
const agent = await apiCall(() => client.agents.get(agentId));

Best Practices

Never let errors propagate unhandled. At minimum, log them.
try {
  await client.agents.delete(agentId);
} catch (error) {
  console.error('Delete failed:', error);
  // Optionally: show user-friendly message
}
Don’t show raw error messages to users. Translate them:
catch (error) {
  const userMessage = error.message === 'Unauthorized'
    ? 'Your session has expired. Please log in again.'
    : 'Something went wrong. Please try again.';
  
  showToast(userMessage);
}
When possible, continue with degraded functionality:
let agents = [];
try {
  agents = await client.agents.list();
} catch (error) {
  console.error('Failed to load agents');
  // Show empty state instead of error
}

return <AgentList agents={agents} />;
Authentication errors won’t be fixed by retrying:
if (error.message === 'Unauthorized') {
  // Don't retry - redirect to login
  throw error;
}