> ## Documentation Index
> Fetch the complete documentation index at: https://docs.wassist.app/llms.txt
> Use this file to discover all available pages before exploring further.

# Error Handling

> Handle errors gracefully in your Wassist integrations

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:

```typescript theme={null}
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:

```typescript theme={null}
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:

```typescript theme={null}
const client = createWassistClient({
  baseUrl: 'https://backend.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:

```typescript theme={null}
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:

```typescript theme={null}
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:

```typescript theme={null}
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

```typescript theme={null}
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:

```typescript theme={null}
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:

```typescript theme={null}
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:

```typescript theme={null}
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:

```typescript theme={null}
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

<AccordionGroup>
  <Accordion title="Always handle errors" icon="shield-check">
    Never let errors propagate unhandled. At minimum, log them.

    ```typescript theme={null}
    try {
      await client.agents.delete(agentId);
    } catch (error) {
      console.error('Delete failed:', error);
      // Optionally: show user-friendly message
    }
    ```
  </Accordion>

  <Accordion title="Provide user feedback" icon="message">
    Don't show raw error messages to users. Translate them:

    ```typescript theme={null}
    catch (error) {
      const userMessage = error.message === 'Unauthorized'
        ? 'Your session has expired. Please log in again.'
        : 'Something went wrong. Please try again.';
      
      showToast(userMessage);
    }
    ```
  </Accordion>

  <Accordion title="Fail gracefully" icon="parachute-box">
    When possible, continue with degraded functionality:

    ```typescript theme={null}
    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} />;
    ```
  </Accordion>

  <Accordion title="Don't retry auth errors" icon="rotate-left">
    Authentication errors won't be fixed by retrying:

    ```typescript theme={null}
    if (error.message === 'Unauthorized') {
      // Don't retry - redirect to login
      throw error;
    }
    ```
  </Accordion>
</AccordionGroup>

## Related

<CardGroup cols={2}>
  <Card title="Authentication" icon="key" href="/sdk/authentication">
    Set up authentication properly.
  </Card>

  <Card title="SDK Overview" icon="code" href="/sdk/overview">
    Return to SDK basics.
  </Card>
</CardGroup>
