Error Handling
Build resilient real-time applications with comprehensive error handling strategies
Overview
Proper error handling is critical for building production-ready real-time applications. Network issues, permission denials, and API errors are inevitable—the difference between a great app and a frustrating one is how gracefully you handle these situations. BaxCloud SDK provides robust error detection and recovery mechanisms to help you build resilient applications.
Network Errors
Connection failures, timeouts, and reconnection handling
Permission Errors
Camera, microphone, and notification access denial
API Errors
Authentication failures, invalid tokens, and rate limits
Common Error Types
Understanding the errors you'll encounter when building with BaxCloud
Connection Errors
Network-related issues that prevent or interrupt the connection to BaxCloud servers.
CONNECTION_TIMEOUT- Server didn't respond within the timeout periodNETWORK_UNAVAILABLE- No internet connection availableCONNECTION_LOST- Connection dropped unexpectedlyRECONNECTION_FAILED- All reconnection attempts exhausted
Permission Errors
User denied access to required device capabilities.
CAMERA_PERMISSION_DENIED- User rejected camera accessMICROPHONE_PERMISSION_DENIED- User rejected microphone accessSCREEN_SHARE_DENIED- User cancelled screen sharingNOTIFICATION_PERMISSION_DENIED- Push notifications blocked
Authentication Errors
Issues with API keys, tokens, or project credentials.
INVALID_API_KEY- API key is incorrect or malformedTOKEN_EXPIRED- Access token has expired and needs refreshUNAUTHORIZED- User doesn't have permission for this actionPROJECT_NOT_FOUND- Invalid project ID
Room Errors
Issues related to room access and capacity.
ROOM_NOT_FOUND- Specified room doesn't existROOM_FULL- Room has reached maximum participant capacityROOM_LOCKED- Room is locked and requires invitationPARTICIPANT_KICKED- User was removed from the room
Media Errors
Problems with accessing or using media devices.
DEVICE_NOT_FOUND- Requested camera or microphone not availableDEVICE_IN_USE- Device is being used by another applicationUNSUPPORTED_FORMAT- Media format not supported on this deviceTRACK_FAILED- Media track encountered an error
Basic Error Handling
Wrap all SDK calls in try/catch blocks to handle errors gracefully
The foundation of error handling is wrapping asynchronous SDK calls in try/catch blocks. This ensures errors don't crash your application and allows you to provide helpful feedback to users.
1import { BaxCloudClient } from '@baxcloud/react-sdk';
2import { useState } from 'react';
3
4export default function VideoCall() {
5 const [error, setError] = useState<string | null>(null);
6
7 const joinRoom = async () => {
8 const client = new BaxCloudClient({
9 projectId: 'your-project-id',
10 apiKey: 'your-api-key',
11 });
12
13 try {
14 await client.connect({
15 roomName: 'meeting-room',
16 liveType: 'video_call',
17 participant: {
18 userId: 'user-123',
19 name: 'John Doe',
20 },
21 });
22
23 setError(null);
24 console.log('Successfully joined room');
25 } catch (error: any) {
26 console.error('Failed to join room:', error);
27 setError(error.message || 'Failed to connect');
28
29 // Show user-friendly error message
30 alert('Unable to join the call. Please check your connection and try again.');
31 }
32 };
33
34 return (
35 <div>
36 {error && (
37 <div className="error-banner">
38 <AlertTriangle /> {error}
39 </div>
40 )}
41 <button onClick={joinRoom}>Join Call</button>
42 </div>
43 );
44}Always Catch Errors
Connection Error Handling
Handle network failures with retry logic and user feedback
Network issues are common in real-time applications. Implement retry logic with exponential backoff to automatically recover from temporary connection failures.
1import { BaxCloudClient } from '@baxcloud/react-sdk';
2import { useState } from 'react';
3
4const MAX_RETRIES = 3;
5const INITIAL_DELAY = 1000; // 1 second
6
7export default function ResilientConnection() {
8 const [isConnecting, setIsConnecting] = useState(false);
9 const [retryCount, setRetryCount] = useState(0);
10
11 const connectWithRetry = async (
12 client: BaxCloudClient,
13 retries = 0
14 ): Promise<void> => {
15 try {
16 setIsConnecting(true);
17 setRetryCount(retries);
18
19 await client.connect({
20 roomName: 'meeting-room',
21 liveType: 'video_call',
22 participant: {
23 userId: 'user-123',
24 name: 'John Doe',
25 },
26 });
27
28 setIsConnecting(false);
29 setRetryCount(0);
30 console.log('Connected successfully');
31 } catch (error: any) {
32 console.error(`Connection attempt ${retries + 1} failed:`, error);
33
34 if (retries < MAX_RETRIES) {
35 // Exponential backoff: 1s, 2s, 4s
36 const delay = INITIAL_DELAY * Math.pow(2, retries);
37
38 console.log(`Retrying in ${delay / 1000} seconds...`);
39 await new Promise(resolve => setTimeout(resolve, delay));
40
41 // Retry connection
42 return connectWithRetry(client, retries + 1);
43 } else {
44 setIsConnecting(false);
45 throw new Error('Failed to connect after multiple attempts');
46 }
47 }
48 };
49
50 const handleConnect = async () => {
51 const client = new BaxCloudClient({
52 projectId: 'your-project-id',
53 apiKey: 'your-api-key',
54 });
55
56 try {
57 await connectWithRetry(client);
58 } catch (error) {
59 alert('Unable to connect. Please check your internet connection.');
60 }
61 };
62
63 return (
64 <div>
65 <button onClick={handleConnect} disabled={isConnecting}>
66 {isConnecting ? `Connecting${retryCount > 0 ? ` (Retry ${retryCount}/${MAX_RETRIES})` : '...'}` : 'Join Call'}
67 </button>
68 </div>
69 );
70}Exponential Backoff
Permission Error Handling
Request permissions gracefully and handle denials
Camera and microphone permissions are essential for video calls. Always check permission status before attempting to access devices, and provide clear guidance when permissions are denied.
1import { BaxCloudClient } from '@baxcloud/react-sdk';
2import { useState } from 'react';
3
4export default function PermissionHandler() {
5 const [permissionError, setPermissionError] = useState<string | null>(null);
6
7 const requestPermissions = async () => {
8 try {
9 // Request camera and microphone access
10 const stream = await navigator.mediaDevices.getUserMedia({
11 video: true,
12 audio: true,
13 });
14
15 // Stop tracks immediately - we just needed to request permission
16 stream.getTracks().forEach(track => track.stop());
17
18 setPermissionError(null);
19 return true;
20 } catch (error: any) {
21 console.error('Permission denied:', error);
22
23 if (error.name === 'NotAllowedError') {
24 setPermissionError('Camera and microphone access denied');
25 return false;
26 } else if (error.name === 'NotFoundError') {
27 setPermissionError('No camera or microphone found');
28 return false;
29 } else {
30 setPermissionError('Unable to access media devices');
31 return false;
32 }
33 }
34 };
35
36 const joinWithPermissions = async () => {
37 // Request permissions first
38 const hasPermissions = await requestPermissions();
39 if (!hasPermissions) {
40 alert('Please enable camera and microphone access in your browser settings.');
41 return;
42 }
43
44 // Now connect to room
45 const client = new BaxCloudClient({
46 projectId: 'your-project-id',
47 apiKey: 'your-api-key',
48 });
49
50 try {
51 await client.connect({
52 roomName: 'meeting-room',
53 liveType: 'video_call',
54 participant: { userId: 'user-123', name: 'John Doe' },
55 });
56
57 await client.enableCamera();
58 await client.enableMicrophone();
59 } catch (error: any) {
60 console.error('Failed to join:', error);
61 alert('Failed to join call: ' + error.message);
62 }
63 };
64
65 return (
66 <div>
67 {permissionError && (
68 <div className="error-banner">
69 <Lock /> {permissionError}
70 <button onClick={() => window.open('chrome://settings/content/camera')}>
71 Open Settings
72 </button>
73 </div>
74 )}
75 <button onClick={joinWithPermissions}>Join Call</button>
76 </div>
77 );
78}Request Early
Media Device Errors
Handle device unavailability and fallback gracefully
Devices can become unavailable for various reasons: already in use, unplugged, or not found. Always handle these scenarios and provide fallback options.
1import { BaxCloudClient } from '@baxcloud/react-sdk';
2
3export default function DeviceErrorHandler() {
4 const handleCameraError = async (client: BaxCloudClient) => {
5 try {
6 await client.enableCamera();
7 } catch (error: any) {
8 console.error('Camera error:', error);
9
10 if (error.name === 'NotFoundError') {
11 alert('No camera found. You can join with audio only.');
12 // Continue without camera
13 await client.enableMicrophone();
14 } else if (error.name === 'NotReadableError') {
15 alert('Camera is being used by another application.');
16 } else {
17 alert('Unable to access camera: ' + error.message);
18 }
19 }
20 };
21
22 const handleMicrophoneError = async (client: BaxCloudClient) => {
23 try {
24 await client.enableMicrophone();
25 } catch (error: any) {
26 console.error('Microphone error:', error);
27
28 if (error.name === 'NotFoundError') {
29 alert('No microphone found. Joining as viewer only.');
30 // Continue without microphone
31 } else if (error.name === 'NotReadableError') {
32 alert('Microphone is being used by another application.');
33 } else {
34 alert('Unable to access microphone: ' + error.message);
35 }
36 }
37 };
38
39 const joinWithFallback = async () => {
40 const client = new BaxCloudClient({
41 projectId: 'your-project-id',
42 apiKey: 'your-api-key',
43 });
44
45 try {
46 await client.connect({
47 roomName: 'meeting-room',
48 liveType: 'video_call',
49 participant: { userId: 'user-123', name: 'John Doe' },
50 });
51
52 // Try to enable camera (with fallback)
53 await handleCameraError(client);
54
55 // Try to enable microphone (with fallback)
56 await handleMicrophoneError(client);
57 } catch (error) {
58 console.error('Failed to join:', error);
59 }
60 };
61
62 return <button onClick={joinWithFallback}>Join Call</button>;
63}Graceful Degradation
Error Event Listeners
Monitor and respond to errors in real-time
BaxCloud SDK emits error events that you can listen to for proactive error handling and monitoring.
1import { BaxCloudClient } from '@baxcloud/react-sdk';
2import { useEffect } from 'react';
3
4export default function ErrorListeners() {
5 useEffect(() => {
6 const client = new BaxCloudClient({
7 projectId: 'your-project-id',
8 apiKey: 'your-api-key',
9 });
10
11 // Listen for connection failures
12 client.on('connectionFailed', (error) => {
13 console.error('Connection failed:', error);
14 showNotification('Connection lost. Attempting to reconnect...');
15 });
16
17 // Listen for reconnection success
18 client.on('reconnected', () => {
19 console.log('Reconnected successfully');
20 showNotification('Connection restored', 'success');
21 });
22
23 // Global error handler
24 client.on('error', (error) => {
25 console.error('SDK error:', error);
26
27 // Log to analytics
28 logErrorToAnalytics({
29 type: error.type,
30 message: error.message,
31 timestamp: new Date().toISOString(),
32 });
33 });
34
35 return () => {
36 client.off('connectionFailed');
37 client.off('reconnected');
38 client.off('error');
39 };
40 }, []);
41
42 return <div>Video Call Interface</div>;
43}Event-Driven Error Handling
Retry Strategies
Implement smart retry logic for different scenarios
Different operations require different retry strategies. Here are common patterns for handling retries.
Exponential Backoff with Max Retries
Best for: Connection failures, API rate limits
1async function retryWithBackoff<T>(
2 operation: () => Promise<T>,
3 maxRetries = 3,
4 initialDelay = 1000
5): Promise<T> {
6 for (let i = 0; i < maxRetries; i++) {
7 try {
8 return await operation();
9 } catch (error) {
10 if (i === maxRetries - 1) throw error;
11
12 const delay = initialDelay * Math.pow(2, i);
13 console.log(`Retry ${i + 1}/${maxRetries} in ${delay}ms`);
14 await new Promise(resolve => setTimeout(resolve, delay));
15 }
16 }
17 throw new Error('Max retries exceeded');
18}
19
20// Usage
21await retryWithBackoff(() => client.connect(options));User-Initiated Retry
Best for: Permission errors, device selection
1import { useState } from 'react';
2
3export default function UserRetry() {
4 const [error, setError] = useState<string | null>(null);
5
6 const attemptConnection = async () => {
7 try {
8 setError(null);
9 await client.connect(options);
10 } catch (err: any) {
11 setError(err.message);
12 }
13 };
14
15 return (
16 <div>
17 {error && (
18 <div className="error-card">
19 <p>{error}</p>
20 <button onClick={attemptConnection}>Try Again</button>
21 </div>
22 )}
23 </div>
24 );
25}Network-Aware Retry
Best for: Mobile apps with variable network conditions
1// React Native example
2import NetInfo from '@react-native-community/netinfo';
3
4async function retryWhenOnline(operation: () => Promise<void>) {
5 const state = await NetInfo.fetch();
6
7 if (!state.isConnected) {
8 console.log('No internet. Waiting for connection...');
9
10 // Wait for network to come back online
11 return new Promise((resolve, reject) => {
12 const unsubscribe = NetInfo.addEventListener(state => {
13 if (state.isConnected) {
14 unsubscribe();
15 operation().then(resolve).catch(reject);
16 }
17 });
18
19 // Timeout after 30 seconds
20 setTimeout(() => {
21 unsubscribe();
22 reject(new Error('Network timeout'));
23 }, 30000);
24 });
25 }
26
27 return operation();
28}
29
30// Usage
31await retryWhenOnline(() => client.connect(options));Best Practices
Always wrap SDK calls in try/catch
Every method that performs async operations can throw errors. Wrapping calls prevents unhandled exceptions from crashing your app.
Provide clear error messages to users
Don't show technical error codes. Translate errors into user-friendly messages with actionable next steps: "Check your internet connection" or "Enable camera access".
Log errors for debugging
Send errors to your analytics or logging service. Include context like user ID, device type, and network conditions to help diagnose issues.
Test error scenarios
Simulate network failures, permission denials, and device errors during development. Use browser DevTools network throttling or test on poor networks.
Have fallback strategies
If camera fails, fallback to audio-only. If connection fails, allow offline mode or queue actions for later. Never leave users stuck.
Monitor error rates in production
Track error types and frequencies. A spike in connection errors might indicate a server issue, while many permission errors suggest UX problems.
Implement timeout handling
Don't let operations hang forever. Set reasonable timeouts (e.g., 10s for connection, 5s for device access) and show feedback to users.
Validate input before SDK calls
Check for empty room names, missing credentials, or invalid options before calling SDK methods. Catch errors early with better error messages.