Skip to main content

Troubleshooting

This guide covers common issues, error codes, and debugging techniques for LLMRTC applications.


Error Codes Reference​

When errors occur, the server sends structured error messages with these codes:

Connection Errors​

CodeDescriptionCommon Causes
WEBRTC_UNAVAILABLEWebRTC not supported or blockedBrowser incompatibility, HTTPS required
CONNECTION_FAILEDConnection establishment failedNetwork issues, firewall blocking UDP
SESSION_NOT_FOUNDSession ID not recognizedReconnecting to expired session
SESSION_EXPIREDSession timed outInactivity beyond TTL (default 30 min)

Provider Errors​

CodeDescriptionCommon Causes
STT_ERRORSpeech-to-text failedInvalid audio, provider API error
STT_TIMEOUTSTT processing exceeded timeoutAudio too long, slow provider
LLM_ERRORLLM inference failedInvalid prompt, API key issues
LLM_TIMEOUTLLM response exceeded timeoutComplex query, provider overload
TTS_ERRORText-to-speech synthesis failedInvalid text, provider API error
TTS_TIMEOUTTTS exceeded timeoutLong text, slow provider

Processing Errors​

CodeDescriptionCommon Causes
AUDIO_PROCESSING_ERRORAudio processing failedCorrupted audio, format mismatch
VAD_ERRORVoice activity detection failedInvalid audio format
INVALID_MESSAGEMalformed protocol messageClient/server version mismatch
INVALID_AUDIO_FORMATUnsupported audio formatWrong sample rate, encoding

Playbook/Tool Errors​

CodeDescriptionCommon Causes
TOOL_ERRORTool execution failedTool threw exception, invalid arguments
PLAYBOOK_ERRORPlaybook orchestration failedInvalid stage, missing handler

Generic Errors​

CodeDescriptionCommon Causes
INTERNAL_ERRORUnexpected server errorBug, resource exhaustion
RATE_LIMITEDToo many requestsProvider rate limit hit

Common Issues​

No Audio / Microphone Blocked​

Symptoms:

  • Browser console shows NotAllowedError: Permission denied
  • No speechStart events triggered
  • Microphone icon not appearing in browser

Solutions:

  1. Ensure the page is served over HTTPS or localhost
  2. Check browser permission settings for the site
  3. Verify getUserMedia is called correctly:
    const stream = await navigator.mediaDevices.getUserMedia({
    audio: {
    echoCancellation: true,
    noiseSuppression: true
    }
    });

WebRTC Connection Fails​

Symptoms:

  • Client stuck in connecting state
  • Browser console shows ICE connection failed
  • Works on localhost but not in production

Log excerpt:

ICE connection state: failed
ICE gathering state: complete
No valid ICE candidates found

Solutions:

  1. Add TURN servers - Required for users behind symmetric NAT:

    const server = new LLMRTCServer({
    metered: {
    appName: 'your-app',
    apiKey: process.env.METERED_API_KEY!
    }
    });
  2. Check firewall rules - Allow UDP on ports 3478, 5349, and 49152-65535

  3. Verify signalling URL matches the server:

    // Client
    const client = new LLMRTCWebClient({
    signallingUrl: 'wss://your-server.com' // Use wss:// for production
    });
  4. Test with STUN only to isolate issues:

    iceServers: [{ urls: 'stun:stun.l.google.com:19302' }]

High Latency​

Symptoms:

  • Long delay between speaking and response
  • Turn-around time > 2 seconds

Diagnosis checklist:

// Add timing hooks to identify bottleneck
hooks: {
onSTTEnd: (ctx, result, timing) => {
console.log(`STT: ${timing.durationMs}ms`);
},
onLLMEnd: (ctx, result, timing) => {
console.log(`LLM: ${timing.durationMs}ms`);
},
onTTSEnd: (ctx, timing) => {
console.log(`TTS: ${timing.durationMs}ms`);
}
}

Solutions by component:

ComponentSolution
STT slowUse whisper-1 model, ensure audio is short
LLM slow (high TTFT)Use gpt-5.6-luna, gpt-5.6-terra, or gemini-3.5-flash; reduce system prompt
LLM slow (streaming)Enable streaming (default)
TTS slowEnable streamingTTS: true; use shorter responses
NetworkDeploy backend closer to users; use edge regions

TTS Produces Silence​

Symptoms:

  • ttsComplete event fires but no audio plays
  • Works in development but not production

Log excerpt:

Error: FFmpeg not found
TTS streaming disabled, falling back to non-streaming

Solutions:

  1. Install FFmpeg (required for streaming TTS):

    # macOS
    brew install ffmpeg

    # Ubuntu/Debian
    apt-get install ffmpeg

    # Docker
    RUN apt-get update && apt-get install -y ffmpeg
  2. Disable streaming TTS if FFmpeg unavailable:

    const server = new LLMRTCServer({
    streamingTTS: false // Uses non-streaming fallback
    });
  3. Check audio element - Client must connect ttsTrack to audio element:

    client.on('ttsTrack', (stream) => {
    const audio = new Audio();
    audio.srcObject = stream;
    audio.play().catch(err => console.error('Playback failed:', err));
    });

Tool Call Errors​

Symptoms:

  • TOOL_ERROR returned to client
  • LLM response incomplete after tool call

Log excerpt:

Tool execution failed: get_weather
Error: Cannot read properties of undefined (reading 'temperature')
Arguments: {"city":"New York"}

Solutions:

  1. Validate JSON Schema matches expected arguments:

    defineTool({
    name: 'get_weather',
    description: 'Get current weather',
    parameters: {
    type: 'object',
    properties: {
    city: { type: 'string', description: 'City name' },
    units: { type: 'string', enum: ['celsius', 'fahrenheit'] }
    },
    required: ['city']
    }
    }, async ({ city, units = 'celsius' }) => {
    // Handle optional parameters with defaults
    });
  2. Add error handling in tool implementation:

    // In the handler function passed to defineTool:
    async (args) => {
    try {
    const data = await fetchWeather(args.city);
    return { temperature: data.temp, condition: data.condition };
    } catch (error) {
    // Return error object instead of throwing
    return { error: 'Weather service unavailable' };
    }
    }
  3. Ensure serializable results - No functions, circular references:

    // Bad: Contains non-serializable data
    return { data: rawResponse, fetch: () => {} };

    // Good: Plain object
    return { temperature: 72, condition: 'sunny' };

Session Drops / Reconnection Issues​

Symptoms:

  • Client repeatedly shows reconnecting then failed
  • SESSION_NOT_FOUND errors on reconnect

Log excerpt:

Reconnect attempt 1/5...
Session abc123 not found
Reconnect attempt 2/5...
Max retries exceeded, connection failed

Solutions:

  1. Handle reconnection gracefully on client:

    client.on('stateChange', (state) => {
    if (state === 'failed') {
    // Start fresh session instead of reconnecting
    client.start(); // Creates new session
    }
    });
  2. Check heartbeat timeout - Client should send pings:

    // Server logs if no heartbeat received
    Heartbeat timeout for session abc123

Rate Limiting​

Symptoms:

  • RATE_LIMITED error code
  • Responses suddenly stop working

Log excerpt:

OpenAI API error: 429 Too Many Requests
Rate limit exceeded. Please retry after 60 seconds.

Solutions:

  1. Implement retry logic - The PlaybookOrchestrator includes built-in retry logic with exponential backoff

  2. Reduce request rate - Increase silence threshold, debounce inputs

  3. Use tiered API plans from your provider


Debug Techniques​

Browser DevTools​

  1. Network tab → WS to inspect WebSocket messages
  2. Look for error message types with codes
  3. Check for failed ICE candidates

Server Logging​

Enable verbose hooks for debugging:

import { createVerboseHooks } from '@llmrtc/llmrtc-core';

const server = new LLMRTCServer({
hooks: createVerboseHooks()
});

Or create targeted logging:

hooks: {
onError: (error, context) => {
console.error(`[${context}] Error:`, error);
},
onToolError: (ctx, request, error) => {
console.error(`Tool ${request.name} failed:`, error);
console.error('Arguments:', request.arguments);
}
}

Connection State Debugging​

client.on('stateChange', (state) => {
console.log(`Connection state: ${state}`);
});

client.on('reconnecting', (attempt, max) => {
console.log(`Reconnect attempt ${attempt}/${max}`);
});