```ERROR:livekit.agents:Error in _audio_forwarding...
# ask-ai
n
Copy code
ERROR:livekit.agents:Error in _audio_forwarding_task
Traceback (most recent call last):
  File "/usr/local/lib/python3.13/site-packages/livekit/agents/voice/generation.py", line 373, in _audio_forwarding_task
    async for frame in tts_output:
    ...<18 lines>...
            await audio_output.capture_frame(frame)
  File "/usr/local/lib/python3.13/site-packages/livekit/agents/utils/aio/channel.py", line 176, in __anext__
    return await self.recv()
           ^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.13/site-packages/livekit/agents/utils/aio/channel.py", line 106, in recv
    await g
asyncio.exceptions.CancelledError

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/local/lib/python3.13/site-packages/livekit/agents/utils/log.py", line 17, in async_fn_logs
    return await fn(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.13/site-packages/livekit/agents/voice/generation.py", line 410, in _audio_forwarding_task
    audio_output.flush()
    ~~~~~~~~~~~~~~~~~~^^
  File "/usr/local/lib/python3.13/site-packages/livekit/agents/voice/transcription/synchronizer.py", line 568, in flush
    self._synchronizer._impl.end_audio_input()
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^
  File "/usr/local/lib/python3.13/site-packages/livekit/agents/voice/transcription/synchronizer.py", line 194, in end_audio_input
    self._audio_data.sr_stream.end_input()
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^
  File "/usr/local/lib/python3.13/site-packages/livekit/agents/voice/transcription/_speaking_rate.py", line 266, in end_input
    self.flush()
    ~~~~~~~~~~^^
  File "/usr/local/lib/python3.13/site-packages/livekit/agents/voice/transcription/_speaking_rate.py", line 262, in flush
    self._input_ch.send_nowait(self._FlushSentinel())
    ~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.13/site-packages/livekit/agents/utils/aio/channel.py", line 92, in send_nowait
    raise ChanClosed
livekit.agents.utils.aio.channel.ChanClosed
Traceback (most recent call last):
  File "/usr/local/lib/python3.13/site-packages/livekit/agents/voice/generation.py", line 373, in _audio_forwarding_task
    async for frame in tts_output:
    ...<18 lines>...
            await audio_output.capture_frame(frame)
  File "/usr/local/lib/python3.13/site-packages/livekit/agents/utils/aio/channel.py", line 176, in __anext__
    return await self.recv()
           ^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.13/site-packages/livekit/agents/utils/aio/channel.py", line 106, in recv
    await g
asyncio.exceptions.CancelledError

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/local/lib/python3.13/site-packages/livekit/agents/utils/log.py", line 17, in async_fn_logs
    return await fn(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.13/site-packages/livekit/agents/voice/generation.py", line 410, in _audio_forwarding_task
    audio_output.flush()
    ~~~~~~~~~~~~~~~~~~^^
  File "/usr/local/lib/python3.13/site-packages/livekit/agents/voice/transcription/synchronizer.py", line 568, in flush
    self._synchronizer._impl.end_audio_input()
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^
  File "/usr/local/lib/python3.13/site-packages/livekit/agents/voice/transcription/synchronizer.py", line 194, in end_audio_input
    self._audio_data.sr_stream.end_input()
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^
  File "/usr/local/lib/python3.13/site-packages/livekit/agents/voice/transcription/_speaking_rate.py", line 266, in end_input
    self.flush()
    ~~~~~~~~~~^^
  File "/usr/local/lib/python3.13/site-packages/livekit/agents/voice/transcription/_speaking_rate.py", line 262, in flush
    self._input_ch.send_nowait(self._FlushSentinel())
    ~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.13/site-packages/livekit/agents/utils/aio/channel.py", line 92, in send_nowait
    raise ChanClosed
livekit.agents.utils.aio.channel.ChanClosed
ERROR:livekit.agents:failed to perform clear buffer rpc
Traceback (most recent call last):
  File "/usr/local/lib/python3.13/site-packages/livekit/agents/voice/avatar/_datastream_io.py", line 179, in _clear_buffer_task
    await self._room.local_participant.perform_rpc(
    ...<3 lines>...
    )
  File "/usr/local/lib/python3.13/site-packages/livekit/rtc/participant.py", line 331, in perform_rpc
    raise RpcError._from_proto(cb.perform_rpc.error)
livekit.rtc.rpc.RpcError: Connection timeout
Traceback (most recent call last):
  File "/usr/local/lib/python3.13/site-packages/livekit/agents/voice/avatar/_datastream_io.py", line 179, in _clear_buffer_task
    await self._room.local_participant.perform_rpc(
    ...<3 lines>...
    )
  File "/usr/local/lib/python3.13/site-packages/livekit/rtc/participant.py", line 331, in perform_rpc
    raise RpcError._from_proto(cb.perform_rpc.error)
livekit.rtc.rpc.RpcError: Connection timeout
WARNING:livekit.agents:didn't receive playback finished event after clear buffer, marking playout as done arbitrarily
WARNING:livekit.agents:playback_finished called more times than playback segments were captured
ERROR:livekit.agents:speech not done in time after interruption, cancelling the speech arbitrarily.
t
Thanks for reaching out, Darshak. I'm an AI assistant and I'm here to help. Give me a moment while I research this topic.
Thanks for sharing the full traceback — that helps a lot. I’m responding to the errors around audio forwarding, channel closure (
ChanClosed
), RPC connection timeouts (
RpcError: Connection timeout
), and the subsequent playback/speech cancellation messages. I don’t have implementation-level logs or source details beyond the traceback you pasted, so I’ll ask a few targeted questions to narrow the cause and then offer troubleshooting steps you can try. Please tell me: • Which LiveKit agents package version are you running? (
pip show livekit-agents
or similar) • Which agent features are enabled (voice avatar, TTS provider, transcription, speaking-rate detection)? • Is this running locally, in a container, or in a cloud environment? Any proxies or network restrictions between the agent and the LiveKit server? • Does the error occur reliably (every run) or intermittently? If intermittent, what triggers it (e.g., manual interruption, network hiccup, long TTS stream)? • Do you have any customizations to channel handling, timeouts, or RPC retry settings? • Are there other logs around the time of this trace on the LiveKit server (connection drops, participant disconnects) or network-level errors? While you gather that info, here are focused troubleshooting steps you can try now: 1. Check for cancelled tasks and channel lifecycle: ◦ The
asyncio.exceptions.CancelledError
+
ChanClosed
indicates a channel or its consumer was closed while the audio-forwarding task was still iterating. Ensure no part of your code cancels the TTS/audio forwarding task prematurely. If you cancel tasks, await their cancellation or catch CancelledError to perform graceful cleanup (flush only if channel still open). 1. Guard flush calls when channels are closed: ◦ The flush path tries to send a sentinel with
send_nowait
, which raises
ChanClosed
. Wrap
send_nowait
or the
flush()
caller in a try/except for
ChanClosed
so it’s safe to call when the receiving end already closed. 1. Investigate RPC connection timeout: ◦ The
perform_rpc
raising
RpcError: Connection timeout
suggests the local participant lost connectivity to the server or RPC deadlines are too short. Check network connectivity and server health. ◦ If you have RPC timeout settings, try increasing them for longer TTS/playback operations. 1. Confirm ordering of playback termination events: ◦ Warnings about “playback_finished called more times than playback segments were captured” suggest race conditions between clearing buffers and receiving playback-finished events. Ensure the code that clears buffers waits for confirmation (or tolerates missing confirmations) and that duplicate finish events are deduplicated. 1. Add defensive logging and retries: ◦ Add logs around channel open/close, task cancellation, and RPC call start/finish to see exact ordering. ◦ For transient RPC timeouts, adding a small retry (with backoff) on
perform_rpc
may help until root network issues are found. 1. Reproduce in a controlled environment: ◦ Try to reproduce with a minimal script that exercises TTS -> audio_output.capture_frame -> flush path. If reproducible, share that minimal reproduction snippet so I can pinpoint which call sequence leads to
ChanClosed
vs. cancellation. If you can provide the version, environment, and answers to the questions above (or a minimal repro), I’ll give a concrete code-level change or patch suggestion to prevent the ChanClosed/timeout cascade and handle the playback finish/deduping cleanly.
n
Which LiveKit agents package version are you running? livekit-agents[openai, cartesia, elevenlabs, deepgram, silero, turn-detector, mcp, google, anthropic, azure, anam, simli, tavus, hedra, lemonslice]==1.4.2 Which agent features are enabled (voice avatar, TTS provider, transcription, speaking-rate detection)? anam, hamsa Is this running locally, in a container, or in a cloud environment? Any proxies or network restrictions between the agent and the LiveKit server? in container, no proxies Does the error occur reliably (every run) or intermittently? If intermittent, what triggers it (e.g., manual interruption, network hiccup, long TTS stream)? intermittently Do you have any customizations to channel handling, timeouts, or RPC retry settings? no
t
Thanks — that extra environment info is really helpful. I’m responding to the intermittent errors you shared: the CancelledError → ChanClosed in the transcription/speaking-rate path, RPC connection timeouts when clearing avatar buffers, and the subsequent playback/speech cancellation warnings. Based on your setup (livekit-agents==1.4.2, containerized, features anam & hamsa, intermittent), here are targeted next steps and practical mitigations to diagnose and reduce these failures. Questions (quick clarifying checks) • Do you see any corresponding disconnects or errors on the LiveKit server logs around the same timestamps? (server-side disconnects would confirm network/RPC issues) • When errors occur, are CPU or memory metrics on the container spiking or being throttled? • Are TTS/LLM providers occasionally slower or returning larger payloads just before the failures? Immediate fixes to try 1. Increase AudioSource buffer to avoid dropped frames ◦ The internal audio queue can overflow under bursty load. Create
AudioSource
with a larger
queue_size_ms
(example: 2000 ms) so frame capture/flush is less sensitive to scheduling delays in the container. 1. Make flush/send robust to closed channels ◦ The stack shows
send_nowait
raising
ChanClosed
. Wrap flush/send calls in try/except for channel closure so cleanup proceeds cleanly without raising: ▪︎ Catch
livekit.agents.utils.aio.channel.ChanClosed
(or a generic channel-closed exception) and treat it as a normal shutdown path. ▪︎ When CancelledError is raised during iteration, catch it and only call flush if the channel is still open. 1. Harden task cancellation and lifecycle handling ◦ Ensure audio-forwarding and transcription tasks are cancelled in a controlled way: ▪︎ When cancelling, await the task and handle
asyncio.CancelledError
inside the task to run cleanup code that checks channel state before sending flush sentinels. ▪︎ Avoid sending to input channels after the receiver has been closed. 1. Increase RPC timeout / add retries for transient RPCs ◦ RPC timeouts (you’re hitting Connection timeout) can be transient. If the framework exposes RPC timeout settings (responseTimeout / connection timeout), increase them for buffer-clear or playback RPCs or add a small retry/backoff on
perform_rpc
. ◦ If no config is exposed, add a lightweight retry wrapper around
perform_rpc
calls that can tolerate a single transient timeout. 1. Deduplicate playback-finished and handle missing confirmations ◦ Warnings show playback_finished called more times than segments captured and also missing playback-finished events. Implement idempotency: ▪︎ Track playback segment IDs and ignore duplicate finish events. ▪︎ If playback-finished is missing after clearing buffer, proceed with a deterministic fallback (mark playout done) but log it as a potentially transient RPC failure. Operational checks to run while reproducing • Watch container CPU/memory and host-level throttling. Bursty CPU throttling in containers causes scheduling latency that surfaces as frame-capture and RPC timeouts. • Correlate timestamps with external TTS/LLM latency spikes (avatar/TTS providers taking longer can delay RPC responses). • Increase logging around these areas: channel open/close events, task cancel/start, perform_rpc start/finish and error details. That will show ordering (which task closes the channel, or if the channel closed due to a disconnect). If you want to reproduce reliably • Create a minimal repro that: 1) Starts an Agent session with the same avatar/TTS flow, 2) Streams a long TTS or intentionally delays avatar response to simulate slowness, 3) Triggers an interruption while TTS is streaming. • Run that while collecting container metrics and verbose agent logs — it will reveal whether timeouts stem from slowness in TTS/avatar or from local task cancellation/race conditions. What I can do next for you • If you can share a short excerpt of the agent code around: audio forwarding task, flush/send sentinel, and the RPC call used to clear buffers, I’ll point out exact try/except placement and show a small patch to safely handle ChanClosed and CancelledError. • Or, share logs that correlate server-side RPC errors or container CPU/memory around the same timestamps and I’ll help interpret them. Summary • Increase audio queue (
queue_size_ms
) to reduce frame drops. • Wrap flush/send in channel-closed-safe logic and handle CancelledError gracefully. • Add retry/increase timeout for critical RPCs (clear buffer/playback events). • Deduplicate/handle missing playback-finished events deterministically. • Monitor container resource usage and external TTS/avatar latency when reproducing. If you’d like, paste the small code fragments mentioned (audio-forwarding loop, flush implementation, and perform_rpc call) and I’ll provide a concise code patch you can drop in to handle these error cases. Sources: client-sdk-js | livekit/livekit_composite | DeepWiki | Tool definition and use | LiveKit Documentation | Agents Framework | livekit/livekit_composite | DeepWiki | Turns overview | LiveKit Documentation | Where to find your Agent Logs | LiveKit