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 ();
}
} }
/>
Microphone Errors Permission and hardware-related issues. // Common microphone errors
- Permission denied
- No microphone detected
- Microphone in use
- Browser not supported
Handling: import { useMicrophonePermission } from '@sammy-labs/sammy-three' ;
function MicrophoneHandler () {
const {
permission ,
isChecking ,
checkPermission ,
requestPermission
} = useMicrophonePermission ();
if ( permission === 'denied' ) {
return (
< Alert type = "error" >
Microphone access denied.
Please enable in browser settings.
</ Alert >
);
}
if ( permission === 'prompt' ) {
return (
< button onClick = { requestPermission } >
Grant Microphone Access
</ button >
);
}
return < AgentInterface /> ;
}
Connection Errors Network and WebSocket issues. // Common connection errors
- Network offline
- WebSocket connection failed
- Server unreachable
- Connection timeout
Handling: < SammyAgentProvider
config = { config }
onConnectionStateChange = { ( connected ) => {
if ( ! connected ) {
showNotification ( 'Connection lost. Reconnecting...' );
}
} }
onError = { ( error ) => {
if ( error . message . includes ( 'WebSocket' ) ||
error . message . includes ( 'network' )) {
// Implement retry logic
retryConnection ();
}
} }
/>
Processing Errors Runtime and resource errors. // Common processing errors
- Memory limit exceeded
- Worker initialization failed
- Audio processing error
- Screen capture failed
Handling: const config = {
// Fallback to main thread if workers fail
observability: {
useWorker: false ,
},
// Reduce quality for memory issues
captureConfig: {
quality: 0.6 ,
},
};
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
Error Cause Solution Token expiredJWT token has expired Implement token refresh logic Microphone permission deniedUser denied access Show instructions to enable in settings WebSocket connection failedNetwork or server issue Retry with exponential backoff Worker initialization failedBrowser doesn’t support workers Disable worker mode in config Audio stutteringPerformance issues Reduce capture quality or frequency Memory limit exceededToo much data in memory Clear cache, reduce quality settings Screen capture failedPermission or browser issue Fall 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