#Hey, we are seeing connection closed but what's the reason?
1 messages · Page 1 of 1 (latest)
Most âconnection closedâ events with our WebSocket TTS endpoints are caused by one of these documented behaviors:
-
Inactivity timeout: the server auto-closes an idle WebSocket after 20 seconds by default. You can:
- Keep it alive by sending a single space character " " periodically (not an empty string).
- Increase the timeout with the query parameter inactivity_timeout (max 180 seconds). (help.elevenlabs.io)
-
Sending an empty string "": on the standard stream-input endpoint this signals End of Sequence and closes the socket. Use " " to keep alive; use "" only to intentionally end. (elevenlabs.io)
-
Using the multi-context endpoint: each context times out after 20 seconds of inactivity (governed by the same inactivity_timeout). To keep a context alive, send an empty text for that context; to close the whole socket, send {"close_socket": true}. (elevenlabs.io)
-
Unsupported model for WebSockets: websockets arenât available for the eleven_v3 model; using it can lead to failed/closed connections. (elevenlabs.io)
-
Auth or quota issues: the WebSocket handshake requires an xi-api-key header; invalid/missing auth or hitting limits (e.g., 401/403/429) will fail and may appear as immediate close. Check the Error messages guide for likely causes such as invalid_api_key or too_many_concurrent_requests. (elevenlabs.io)
Quick next steps to diagnose:
- Confirm which endpoint youâre using (stream-input vs multi-stream-input) and how youâre signaling keep-alive/end. (elevenlabs.io)
- Log the exact close timing (â20s suggests idle timeout) and verify whether your client is sending " " vs "". (help.elevenlabs.io)
- Try setting inactivity_timeout to a higher value (e.g., 180) and see if the close timing matches the new value. (elevenlabs.io)
- Verify the xi-api-key is present/valid and youâre not exceeding concurrency/usage limits. (elevenlabs.io)
If you share which endpoint, model, and any server messages you see just before the close, I can point to the exact cause per the docs. (elevenlabs.io)
persona_backend | File "/app/.venv/lib/python3.11/site-packages/livekit/agents/tts/tts.py", line 357, in _main_task
persona_backend | await self._run(output_emitter)
persona_backend | File "/app/.venv/lib/python3.11/site-packages/livekit/plugins/elevenlabs/tts.py", line 425, in _run
persona_backend | raise e
persona_backend | File "/app/.venv/lib/python3.11/site-packages/livekit/plugins/elevenlabs/tts.py", line 420, in _run
persona_backend | await waiter
persona_backend | livekit.agents._exceptions.APIStatusError: connection closed (status_code=-1, request_id=None, body=None, retryable=True)
persona_backend | {"message": "websocket closed unexpectedly", "level": "WARNING", "name": "livekit.plugins.elevenlabs", "pid": 58, "job_id": "AJ_QUuKUyC6R66p", "timestamp": "2025-09-24T08:14:40.482568+00:00"}
persona_backend | {"message": "failed to synthesize speech, retrying in 0.1s\nTraceback (most recent call last):\n File \"/app/.venv/lib/python3.11/site-packages/livekit/agents/tts/tts.py\", line 357, in _main_task\n await self._run(output_emitter)\n File \"/app/.venv/lib/python3.11/site-packages/livekit/plugins/elevenlabs/tts.py\", line 425, in _run\n raise e\n File \"/app/.venv/lib/python3.11/site-packages/livekit/plugins/elevenlabs/tts.py\", line 420, in _run\n await waiter\nlivekit.agents._exceptions.APIStatusError: connection closed (status_code=-1, request_id=None, body=None, retryable=True)", "level": "WARNING", "name": "livekit.agents", "tts": "livekit.plugins.elevenlabs.tts.TTS", "attempt": 1, "streamed": true, "pid": 58, "job_id": "AJ_QUuKUyC6R66p", "timestamp": "2025-09-24T08:14:40.483493+00:00"}
persona_backend | INFO: 127.0.0.1:43056 - "GET /api/v1/health HTTP/1.1" 200 OK```
Most likely cause (per ElevenLabs docs): the TTS WebSocket closes automatically after a period of inactivity. By default it auto-closes after 20 seconds with no incoming messages. Sending an empty string "" also signals EndâofâSequence and closes the socketâthis often surfaces as âwebsocket closed unexpectedly.â (help.elevenlabs.io)
How to prevent it:
- Send a keepalive: transmit a single space character " " periodically to reset the inactivity timer. (help.elevenlabs.io)
- Increase the inactivity window: add inactivity_timeout as a query parameter (max 180 seconds), e.g. wss://api.elevenlabs.io/v1/text-to-speech/{voice_id}/stream-input?model_id=...&inactivity_timeout=180. (help.elevenlabs.io)
- Ensure your client never sends an empty string unless you intend to close the connection. (elevenlabs.io)
If youâre not truly streaming input (you have the full text up front), consider the HTTP streaming (SSE) endpoint instead of WebSockets for simpler, more robust behavior. (help.elevenlabs.io)
Sources:
How can I keep the WebSocket open? â ElevenLabs
How can I keep the WebSocket open? â ElevenLabs
How can I keep the WebSocket open? â ElevenLabs
Generate audio in real-time | ElevenLabs Documentation
What is the Text-to-Speech WebSockets API? â ElevenLabs
persona_backend | {"message": "websocket closed unexpectedly", "level": "WARNING", "name": "livekit.plugins.elevenlabs", "pid": 58, "job_id": "AJ_QUuKUyC6R66p", "timestamp": "2025-09-24T08:14:41.440689+00:00"}
persona_backend | 2025-09-24 08:14:41,441 - livekit.agents - WARNING - failed to synthesize speech, retrying in 2.0s
persona_backend | Traceback (most recent call last):
persona_backend | File "/app/.venv/lib/python3.11/site-packages/livekit/agents/tts/tts.py", line 357, in _main_task
persona_backend | await self._run(output_emitter)
persona_backend | File "/app/.venv/lib/python3.11/site-packages/livekit/plugins/elevenlabs/tts.py", line 425, in _run
persona_backend | raise e
persona_backend | File "/app/.venv/lib/python3.11/site-packages/livekit/plugins/elevenlabs/tts.py", line 420, in _run
persona_backend | await waiter
persona_backend | livekit.agents._exceptions.APIStatusError: connection closed (status_code=-1, request_id=None, body=None, retryable=True)```
Most often this happens because the ElevenLabs TTS WebSocket autoâcloses after 20 seconds of inactivity. If your app pauses between text messages, the server will close the socket and youâll see âwebsocket closed unexpectedly.â You can either send a keepâalive single space " " periodically or increase the inactivity timeout. (elevenlabs.io)
What to check and fix
- Keep the connection alive: send " " at least every 20s, or add inactivity_timeout (max 180) to the WS URL, e.g. âŠ/stream-input?model_id=âŠ&inactivity_timeout=180. Note: sending an empty string "" signals endâofâsequence and closes the socket. (elevenlabs.io)
- Model compatibility: WebSockets are not available for the eleven_v3 model; use a supported TTS model (e.g., eleven_flash_v2_5). (elevenlabs.io)
- Authentication: include your xi_api_key in the first WebSocket message; invalid or missing keys will fail authentication. (elevenlabs.io)
- Concurrency/rate limits: exceeding concurrency can yield 429sâretry with backoff. (elevenlabs.io)
- Optional: you can pin to a region (e.g., api.us.elevenlabs.io) if you want to control server location. (elevenlabs.io)
Relevant docs:
- Generate audio in real time (WebSockets): inactivity behavior, keepâalives, empty string closes. (elevenlabs.io)
- Help Center: keeping the WebSocket open and inactivity_timeout up to 180s. (help.elevenlabs.io)
- Blog: custom inactivity timeout (max 180s). (elevenlabs.io)
- Error messages: invalid_api_key, concurrency (429). (elevenlabs.io)
- Specifying server location. (elevenlabs.io)
If you share the exact WS URL (minus your key) and the model youâre using, I can point to the precise change needed.
Sources:
Generate audio in real-time | ElevenLabs Documentation
Generate audio in real-time | ElevenLabs Documentation
Generate audio in real-time | ElevenLabs Documentation
Generate audio in real-time | ElevenLabs Documentation
Error messages | ElevenLabs Documentation
Specifying server location - ElevenLabs
Generate audio in real-time | ElevenLabs Documentation
How can I keep the WebSocket open? â ElevenLabs
WebSocket-förbÀttringar: tillförlitlighet och anpassad timeout | ElevenLabs
Error messages | ElevenLabs Documentation
Specifying server location - ElevenLabs
persona_backend | {"message": "websocket closed unexpectedly", "level": "WARNING", "name": "livekit.plugins.elevenlabs", "pid": 58, "job_id": "AJ_QUuKUyC6R66p", "timestamp": "2025-09-24T08:14:44.316155+00:00"}```