Skip to main content

Error Handling

Build resilient applications with comprehensive error handling for all SAMMY Three scenarios.

Overview

SAMMY Three provides multiple layers of error handling to ensure your application remains stable and provides a good user experience even when things go wrong.

Provider-Level

Global error boundaries for application-wide issues

Component-Level

Granular error handling for specific features

Recovery Strategies

Automatic retry and fallback mechanisms

Error Types

Understanding different error types helps you handle them appropriately.
  • Authentication
  • Microphone
  • Connection
  • Processing

Authentication Errors

Errors related to JWT tokens and API access.
// Common authentication errors
- Token expired
- Invalid token format
- Missing authentication
- Insufficient permissions
Handling:
<SammyAgentProvider
  config={config}
  onTokenExpired={async () => {
    // Refresh token
    const newToken = await refreshAuthToken();
    updateConfig({ auth: { token: newToken } });
  }}
  onError={(error) => {
    if (error.message.includes('401') || 
        error.message.includes('token')) {
      // Redirect to login
      redirectToLogin();
    }
  }}
/>

Implementation Patterns

Provider-Level Error Boundary

Implement a global error boundary for unhandled errors.
import { SammyAgentProvider } from '@sammy-labs/sammy-three';
import { ErrorBoundary } from 'react-error-boundary';

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

function App() {
  return (
    <ErrorBoundary
      FallbackComponent={ErrorFallback}
      onReset={() => window.location.reload()}
    >
      <SammyAgentProvider
        config={config}
        onError={(error) => {
          // Log to error tracking service
          logErrorToService(error);
          
          // Show user-friendly message
          showErrorNotification(error);
        }}
      >
        <YourApp />
      </SammyAgentProvider>
    </ErrorBoundary>
  );
}

Component-Level Error Handling

Handle errors at the component level for better UX.
function ChatComponent() {
  const { 
    error, 
    agentStatus, 
    startAgent 
  } = useSammyAgentContext();
  
  const [localError, setLocalError] = useState(null);
  const [retryCount, setRetryCount] = useState(0);
  
  const handleStart = async () => {
    try {
      setLocalError(null);
      const success = await startAgent({
        agentMode: 'user',
      });
      
      if (!success) {
        throw new Error('Failed to start agent');
      }
      
      setRetryCount(0);
    } catch (error) {
      setLocalError(error);
      
      // Implement exponential backoff
      if (retryCount < 3) {
        setTimeout(() => {
          setRetryCount(prev => prev + 1);
          handleStart();
        }, Math.pow(2, retryCount) * 1000);
      }
    }
  };
  
  if (localError) {
    return (
      <div className="error-state">
        <p>Error: {localError.message}</p>
        <button onClick={handleStart}>
          Retry ({3 - retryCount} attempts remaining)
        </button>
      </div>
    );
  }
  
  return (
    <div>
      <button onClick={handleStart}>
        Start Agent
      </button>
    </div>
  );
}

Error Recovery Strategies

Automatic Retry

Implement exponential backoff for transient errors.
async function retryWithBackoff(
  fn: () => Promise<any>,
  maxRetries = 3,
  baseDelay = 1000
) {
  for (let i = 0; i < maxRetries; i++) {
    try {
      return await fn();
    } catch (error) {
      if (i === maxRetries - 1) throw error;
      
      const delay = baseDelay * Math.pow(2, i);
      await new Promise(resolve => setTimeout(resolve, delay));
    }
  }
}

// Usage
const result = await retryWithBackoff(() => 
  startAgent({ agentMode: 'user' })
);

Graceful Degradation

Provide fallback functionality when features fail.
function AgentInterface() {
  const { agentStatus, error } = useSammyAgentContext();
  const [fallbackToText, setFallbackToText] = useState(false);
  
  useEffect(() => {
    if (error?.message.includes('microphone')) {
      setFallbackToText(true);
    }
  }, [error]);
  
  if (fallbackToText) {
    return <TextChatInterface />;
  }
  
  return <VoiceAgentInterface />;
}

User Communication

Keep users informed about errors and recovery.
function ErrorNotification({ error, onRetry }) {
  const getMessage = (error) => {
    if (error.message.includes('token')) {
      return 'Session expired. Please log in again.';
    }
    if (error.message.includes('microphone')) {
      return 'Microphone access required for voice chat.';
    }
    if (error.message.includes('network')) {
      return 'Connection lost. Checking network...';
    }
    return 'Something went wrong. Please try again.';
  };
  
  return (
    <Alert 
      type="error"
      action={
        <button onClick={onRetry}>Retry</button>
      }
    >
      {getMessage(error)}
    </Alert>
  );
}

Debugging Errors

Enable Debug Mode

Get detailed error information during development.
const config = {
  debugLogs: true,
  observability: {
    enabled: true,
    logToConsole: true,
  },
};

// Additional debugging in console
window.addEventListener('unhandledrejection', event => {
  console.error('Unhandled promise rejection:', event.reason);
});

Error Tracking

Integrate with error tracking services.
import * as Sentry from '@sentry/react';

Sentry.init({
  dsn: 'YOUR_SENTRY_DSN',
  integrations: [
    new Sentry.BrowserTracing(),
  ],
});

function App() {
  return (
    <Sentry.ErrorBoundary fallback={ErrorFallback}>
      <SammyAgentProvider
        config={config}
        onError={(error) => {
          Sentry.captureException(error, {
            tags: {
              component: 'sammy-agent',
            },
            extra: {
              agentStatus: agentStatus,
              config: config,
            },
          });
        }}
      >
        <YourApp />
      </SammyAgentProvider>
    </Sentry.ErrorBoundary>
  );
}

Error Prevention

Validate Configuration: Check config values before initializing
Check Permissions Early: Request microphone access before starting agent
Monitor Resources: Track memory and CPU usage to prevent crashes
Test Error Scenarios: Simulate errors in development to test handling
Provide Fallbacks: Always have alternative paths for critical features

Common Error Solutions

Quick Reference

ErrorCauseSolution
Token expiredJWT token has expiredImplement token refresh logic
Microphone permission deniedUser denied accessShow instructions to enable in settings
WebSocket connection failedNetwork or server issueRetry with exponential backoff
Worker initialization failedBrowser doesn’t support workersDisable worker mode in config
Audio stutteringPerformance issuesReduce capture quality or frequency
Memory limit exceededToo much data in memoryClear cache, reduce quality settings
Screen capture failedPermission or browser issueFall back to alternative capture method

Testing Error Scenarios

Simulating Errors

Test your error handling by simulating different scenarios:
// Simulate token expiration
setTimeout(() => {
  localStorage.removeItem('auth_token');
  window.dispatchEvent(new Event('token_expired'));
}, 30000);

// Simulate network disconnection
window.addEventListener('online', () => console.log('Back online'));
window.addEventListener('offline', () => console.log('Gone offline'));

// Simulate microphone disconnection
navigator.mediaDevices.addEventListener('devicechange', () => {
  console.log('Audio devices changed');
});

Error Testing Checklist

  • Authentication
  • Audio
  • Network
  • Resources
  • Invalid token format
  • Expired token
  • Missing token
  • Insufficient permissions
  • Rate limiting
I