Skip to content

fix: propagate RealtimeError from generate_reply timeout (#6224)#6226

Open
C1-BA-B1-F3 wants to merge 2 commits into
livekit:mainfrom
C1-BA-B1-F3:fix/generate-reply-timeout-propagation
Open

fix: propagate RealtimeError from generate_reply timeout (#6224)#6226
C1-BA-B1-F3 wants to merge 2 commits into
livekit:mainfrom
C1-BA-B1-F3:fix/generate-reply-timeout-propagation

Conversation

@C1-BA-B1-F3

Copy link
Copy Markdown

Fixes #6224. The wait_if_not_interrupted method used asyncio.gather(return_exceptions=True) which swallowed RealtimeError exceptions from the generate_reply timeout future.

wait_if_not_interrupted used asyncio.gather(return_exceptions=True) which
swallowed exceptions from the generate_reply future. Now checks results
and re-raises any non-cancelled exceptions.
@C1-BA-B1-F3 C1-BA-B1-F3 requested a review from a team as a code owner June 25, 2026 10:48
@CLAassistant

CLAassistant commented Jun 25, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

devin-ai-integration[bot]

This comment was marked as resolved.

…upted

The else branch added to wait_if_not_interrupted re-raised ALL exceptions
from gathered futures, which broke callers that relied on the old behavior
where exceptions were captured via return_exceptions=True and callers
inspected them manually via Future.result().

Specifically:
- ChanClosed (normal end-of-generation) was re-raised before _next_segment
  could catch it via recv.result(), crashing the pipeline.
- Other callers (generation.py, filler_scheduler.py, tool execution) were
  also affected.

The PR's real fix - adding speech_handle._mark_done(error=e) at the caller
sites in agent_activity.py - is preserved and correctly propagates
RealtimeError to the SpeechHandle without needing wait_if_not_interrupted
to re-raise exceptions.

@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 found 1 new potential issue.

Open in Devin Review

Comment on lines +1809 to +1820
session = create_session(FakeActions(), speed_factor=1.0)
# Replace the LLM with our fake realtime model
session._llm = _FakeRealtimeModel()

agent = MyAgent()

with pytest.raises(RealtimeError, match="generate_reply timed out"):
async with session:
await agent.start(session)
# generate_reply should raise RealtimeError instead of hanging
handle = session.generate_reply(instructions="say hello")
await handle

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.

🚩 Test monkey-patches session._llm which may not exercise the full realtime path

The test at tests/test_agent_session.py:1811 sets session._llm = _FakeRealtimeModel() after session creation. Since create_session(FakeActions()) constructs the session with a non-realtime LLM, the AgentActivity created when the agent starts may not initialize its _rt_session properly. Whether this test actually triggers the _realtime_reply_task code path depends on whether AgentActivity re-reads session._llm at startup vs. caching it. If the realtime session is not set up, the assertion assert self._rt_session is not None at line 3183 would fire instead of reaching the intended error path. Worth verifying the test passes in CI.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

@longcw longcw 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.

looks good to me! can you fix the CI and move the test to test_realtime?

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.

llm.RealtimeError("generate_reply timed out.") for "failed to generate a reply: generate_reply timed out" cannot be captured by exception

3 participants