Skip to content

fix(voice): don't drop the realtime turn when the chat-ctx push times out#6445

Open
ByteMaster-1 wants to merge 1 commit into
livekit:mainfrom
ByteMaster-1:fix/update-chat-ctx-timeout
Open

fix(voice): don't drop the realtime turn when the chat-ctx push times out#6445
ByteMaster-1 wants to merge 1 commit into
livekit:mainfrom
ByteMaster-1:fix/update-chat-ctx-timeout

Conversation

@ByteMaster-1

Copy link
Copy Markdown
Contributor

Incident. Calling session.generate_reply(user_input=...) on a realtime session pushes the message via update_chat_ctx before requesting the reply. That await was unguarded: when the OpenAI plugin's 5s ack timeout fired (RealtimeError("update_chat_ctx timed out.")), the error propagated as an unhandled exception in the turn task — the turn died, the user got silence, and nothing was reported on the SpeechHandle.

Fix. The push is best-effort — the plugin sends all conversation.item.create events before waiting for acks, so a timeout means missing acknowledgements, not missing items. So:

RealtimeError → log a warning and still call generate_reply (the server usually has the context).
Unexpected exceptions → mark the SpeechHandle done with the error, observable via SpeechHandle.exception() #6304 , without crashing the turn task.
Deliberately out of scope: no retry of the push itself, and no change to the plugin's timeout; the two other update_chat_ctx call sites (interrupted-sync and tool-output paths) already have their own RealtimeError handling and are untouched.

… out

In _realtime_reply_task the chat-context push before generate_reply was a bare
await: the OpenAI plugin raises RealtimeError("update_chat_ctx timed out.")
after its 5s ack timeout, which propagated as an unhandled task error and
killed the turn — the user asked a question and got silence.

The push is best-effort: the plugin sends all conversation.item.create events
before waiting for acks, so on timeout the server usually already has the
items. Handle it accordingly:

- RealtimeError (provider-reported, e.g. ack timeout): log and proceed with
  generate_reply anyway
- any other exception: mark the SpeechHandle done with the error so the app
  observes the failed turn via SpeechHandle.exception() instead of a crashed
  task
@ByteMaster-1 ByteMaster-1 requested a review from a team as a code owner July 15, 2026 17:25

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no potential bugs to report.

View in Devin Review to see 1 additional finding.

Open in Devin Review

@ByteMaster-1

Copy link
Copy Markdown
Contributor Author

@longcw This is the second follow-up from the #6352 rescope: the update_chat_ctx push inside generate_reply no longer kills the turn on the plugin's ack timeout (best-effort — the items were already sent), and unexpected failures land on SpeechHandle.exception() instead of crashing the turn task. Small diff + unit tests. PTAL when you get a chance.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant