Skip to content

Intermittent: /run_sse SSE connection sometimes does not close after final model response #4216

@iamirulofficial

Description

@iamirulofficial

Summary

When using the /run_sse endpoint in google/adk-python (v1.22.1), the SSE stream sometimes does not close after the model's final response. Other times, the connection closes properly.

Details

  • Repository: google/adk-python
  • Version: 1.22.1
  • Model: Claude (claude-opus-4-5-20251101) via LiteLLM backend
  • Endpoint: /run_sse
  • Client: Browser/Angular with fetch and streaming response parsing , I am using my own UI

Observed Behavior

  • The SSE connection usually closes as expected after the final text-only model message (no function call parts).
  • However, in some runs (see example 1 below), the server keeps the connection open even after sending the final message. The client waits for more data forever.
  • There is no explicit turnComplete or done:true signal. The client must rely on fragile heuristics which are not robust to all edge cases.

Example 1: Connection stays open

my sessions are usually 5 to 10mins long
(Final event)

{"content":{"parts":[{"text":"Fixed!  Added the missing `required` array... "}]}, ... }

— Connection does not close after this (bug)

Example 2: Connection closes as expected

(Final event)

{"content":{"parts":[{"text":"Your portfolio is ready! ..."}]}, ... }

— Connection closes as expected

What we've tried

  • Attempted to detect stream completion by checking message structure, but this workaround does not work in all cases as sometimes the stream does close properly, sometimes it doesn't.
  • Adding client-side completion timeouts as a hacky workaround, but this is not ideal.

Expected Behavior

  • The SSE connection should ALWAYS close after the model's final response, not randomly.
  • (Ideally) The server should send a clear termination signal: either closing the HTTP stream or emitting an explicit { "done": true } or similar message before closing.

Impact

  • Causes frontends to hang indefinitely (no timeout event) and makes completion detection fragile.
  • Client cannot reliably distinguish between server inactivity, error, or true completion.

Possible Causes (hypotheses)

  • Async generator (runner.run_async()) not always completing cleanly
  • Some internal ADK state or tool connections keep the generator alive on certain tool execution chains
  • Lack of an explicit "done" signal makes client-side detection error-prone

Request

  • Please investigate why, under some (but not all) flows, the stream stays open after the model finishes.
  • Please either:
    • Fix the runner.run_async()/SSE handler to always close the HTTP response after the final turn, OR
    • Send an explicit termination/"done" event at the end so clients can handle this robustly.

Additional Context

  • If helpful, I can provide full sample logs/events for both the working and non-working cases.

Metadata

Metadata

Assignees

Labels

answered[Status] This issue has been answered by the maintainerweb[Component] This issue will be transferred to adk-web

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions