Skip to content

ElevenLabs TTS: WebSocket closes unexpectedly + Unclosed aiohttp ClientSession #4676

@YTzcn

Description

@YTzcn

Bug Description

When using ElevenLabs TTS in a LiveKit voice agent, two issues occur:
WebSocket closes unexpectedly
The streaming TTS WebSocket (multi-stream-input) connects, then closes shortly after with no HTTP status (status_code=-1). Logs show:
elevenlabs tts returned error
websocket closed unexpectedly
APIStatusError: connection closed (status_code=-1, request_id=None, body=None, retryable=True)
Unclosed aiohttp session
After the agent runs:
Unclosed client session
Unclosed connector

Expected Behavior

WebSocket remains open for the duration of synthesis (or fails with a clear status).
aiohttp ClientSession is closed when the TTS instance/stream is torn down.

Reproduction Steps

Create a LiveKit voice agent using ElevenLabs TTS: elevenlabs.TTS(voice_id=..., model="eleven_turbo_v2_5", language="tr", inactivity_timeout=300).
Run a real-time call (e.g. SIP inbound); pipeline uses tts.stream().
When the agent synthesizes (e.g. first greeting), the WebSocket to ElevenLabs drops; retries fail with the same error.
After the session ends, "Unclosed client session" / "Unclosed connector" appear.

Operating System

ubuntu server

Models Used

Elevenlabs STT Models

Package Versions

Package: livekit-plugins-elevenlabs 1.3.12
Python: 3.11
Usage: LiveKit Voice Agent; TTS via tts.stream() (streaming WebSocket)

Session/Room/Call IDs

No response

Proposed Solution

Additional Context

REST TTS (POST /v1/text-to-speech/{voice_id}) works with the same API key and model; issue is only with streaming WebSocket (multi-stream-input).
No 403; failure is "connection closed" with no body.
Reproduced with model="eleven_turbo_v2_5", language="tr"; also seen with eleven_flash_v2_5. Close happens soon after connect, not after idle.
Questions
Does the streaming WebSocket endpoint require a specific ElevenLabs plan (e.g. Conversational AI) that could explain connection closed with no status?
Can the plugin be updated to close the aiohttp ClientSession when the TTS is closed, or document that callers must pass and close their own http_session?

Screenshots and Recordings

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions