From f11b6d7151b30db01148ae8a4f56a510de982e80 Mon Sep 17 00:00:00 2001 From: Paul Kompfner Date: Fri, 3 Apr 2026 16:30:03 -0400 Subject: [PATCH] Fix Gemini Live session resumption hanging after reconnect After a reconnect, _ready_for_realtime_input was never set back to True because _create_initial_response (which sets the flag) is only called on initial connection. This caused all audio/video/text to be silently dropped after reconnecting, making the bot appear to hang. Set the flag in _handle_session_ready when we detect a reconnect, either via session_resumption_handle (server restores state) or via existing context (rare case where connection drops before first resumption handle). --- changelog/4242.fixed.md | 1 + .../services/google/gemini_live/llm.py | 22 +++++++++++++++---- 2 files changed, 19 insertions(+), 4 deletions(-) create mode 100644 changelog/4242.fixed.md diff --git a/changelog/4242.fixed.md b/changelog/4242.fixed.md new file mode 100644 index 000000000..e987773df --- /dev/null +++ b/changelog/4242.fixed.md @@ -0,0 +1 @@ +- Fixed Gemini Live bot hanging after a session resumption reconnect. Audio, video, and text input were silently dropped after reconnecting because the internal `_ready_for_realtime_input` flag was not being reset. diff --git a/src/pipecat/services/google/gemini_live/llm.py b/src/pipecat/services/google/gemini_live/llm.py index 66900fc6e..3e3cbd092 100644 --- a/src/pipecat/services/google/gemini_live/llm.py +++ b/src/pipecat/services/google/gemini_live/llm.py @@ -1355,14 +1355,28 @@ class GeminiLiveLLMService(LLMService): async def _handle_session_ready(self, session: AsyncSession): """Handle the session being ready.""" self._session = session - # If we were just waititng for the session to be ready to run the LLM, - # do that now. if self._run_llm_when_session_ready: + # Initial connection: context arrived before session was ready. self._run_llm_when_session_ready = False await self._create_initial_response() - elif self._context: - # Reconnect case: context already exists, no need for _create_initial_response + elif self._session_resumption_handle: + # Reconnect with session resumption: the server will restore + # session state, so we can accept realtime input right away. self._ready_for_realtime_input = True + elif self._context: + # Reconnect without session resumption (e.g. error occurred + # before server sent a resumption handle). + # TODO: ideally we'd re-send conversation history here via + # _create_initial_response(), but that currently doesn't handle + # the reconnect case properly. This should be very rare — the + # connection would have to drop before we've received our first + # session_resumption_handle from the server. + self._ready_for_realtime_input = True + else: + # Initial connection: session is ready before context has + # arrived. Nothing to do — _handle_context will call + # _create_initial_response when the context arrives. + pass async def _handle_msg_model_turn(self, msg: LiveServerMessage): """Handle the model turn message."""