fix(voice): force-interrupt outdated reply in _user_turn_completed_task#6451
Open
mpg-kaoru-hotate wants to merge 1 commit into
Open
Conversation
When a new user turn starts while a previous _user_turn_completed_task
is still running, the older task discards its now-outdated reply via
speech_handle.interrupt(). The handle inherits the session's
allow_interruptions, so with interruption disabled
(turn_handling.interruption.enabled=False) this internal cleanup raised
RuntimeError("This generation handle does not allow interruptions"),
aborted the rest of the task (EOU metrics), and left the outdated reply
scheduled for playout.
Use interrupt(force=True): this is internal cleanup of a reply that
should never play, not a user-initiated interruption.
Fixes livekit#4443
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
|
longcw
approved these changes
Jul 16, 2026
longcw
left a comment
Contributor
There was a problem hiding this comment.
thanks for the pr! could you sign t he CLA before we merge it
This was referenced Jul 17, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #4443
Root cause
When a new user turn starts while a previous
_user_turn_completed_taskis still running, the older task detects it is outdated and discards its reply:speech_handlewas just created by_generate_reply()and inherits the session'sallow_interruptions. When interruptions are disabled (turn_handling={"interruption": {"enabled": False}}, orAgent(allow_interruptions=False)),interrupt()withoutforce=Trueraises:Consequences beyond the noisy error log:
This is internal cleanup of a reply that should never play — not a user-initiated interruption — so it should bypass the
allow_interruptionsguard withforce=True. All other internalinterrupt()call sites inagent_activity.pyalready either passforce=Trueor checkallow_interruptionsfirst; this was the only unguarded one.Reproduction
We hit this in production (telephony agent with interruptions disabled to suppress line-echo false positives) whenever the user produced consecutive turns in quick succession — e.g. speaking again right after end-of-turn was detected, or STT splitting one utterance into multiple finals. Traceback from Sentry matches the one reported in #4443:
The added regression test (
test_consecutive_user_turns_when_interruptions_disabled) reproduces exactly this traceback onmainwithout the fix, and passes with it. It mirrors the existingtest_interrupt_during_on_user_turn_completedscenario (second user turn arriving whileon_user_turn_completedof the first turn is still running) withinterruption.enabled=False.Testing
pytest tests/test_agent_session.py— 55 passed (including the 2 new parametrized cases)ruff check/ruff formatclean🤖 Generated with Claude Code