[Bug] SSE stream stalls in long-running sessions without message_stop event

Open 💬 14 comments Opened Apr 28, 2026 by KingPin

SSE stream from /v1/messages stalls mid-response main-thread requests (no message_stop, no error event)

Summary

In long-running interactive Claude Code sessions, SSE responses from /v1/messages repeatedly stop emitting events mid-response without sending message_stop or any error event. The connection stays open and the client correctly waits — but no further bytes arrive. Most stalls recover on their own after ~50–70s; some never recover and only resolve when the user presses ESC. Subagent streams in the same session are unaffected.

Claude Code's own [Stall] telemetry (stream_idle_partial, Streaming stall detected, Streaming completed with N stall(s)) cleanly captures the behavior — this issue is filing what that telemetry is reporting.

Environment

  • Claude Code version: 2.1.119 (native install, cc_version=2.1.119.9c7, entrypoint cli)
  • Model: claude-opus-4-7 and claude-sonnet-4-6
  • Subscription: Team, rateLimitTier=default_claude_max_5x
  • OS: Linux 7.0.0-1-cachyos, terminal Konsole 26.04.0
  • Relevant env:
  • CLAUDE_STREAM_IDLE_TIMEOUT_MS=900000
  • API_TIMEOUT_MS=600000
  • CLAUDE_CODE_DISABLE_ADAPTIVE_THINKING=1
  • CLAUDE_CODE_DISABLE_1M_CONTEXT=1

Reproduction

Not deterministic but very high frequency: in a single 26-minute working session (b3ad7516-35cd-47cb-9e98-6916ee362882), 5 distinct stalls occurred — roughly one every five minutes of active use. Behavior reproduces across sessions.

The stalls happen during normal multi-turn coding work (tool calls + bash + edits). No special conditions required.

Observed behavior (from debug log)

All five stalls were on source=repl_main_thread, each with a different x-client-request-id. All stalled early in the response (under ~5.4KB / ~1000 tokens streamed), and then went silent with the connection still open.

| # | Stall start (UTC) | x-client-request-id | Bytes when frozen | Outcome |
|---|---|---|---|---|
| 1 | 2026-04-26T19:25:46Z | 721d0de1-200f-422e-b7c8-c90dd211f62c | 737 | Recovered after 51.8s |
| 2 | 2026-04-26T19:28:45Z | 2f671a02-f62f-433a-8cae-6ac3afdb1832 | 4336 | Recovered after 67.6s |
| 3a | 2026-04-26T19:40:43Z | 2f39599a-9ce9-4d65-ba2d-6476635db3b4 | 659 | Recovered after ~16s |
| 3b | 2026-04-26T19:41:17Z | 307a8268-8e8a-4afd-ab90-8ac8efc4c722 | 653 | Recovered after ~8s |
| 4 | 2026-04-26T19:45:57Z | 28380ec8-29ba-4e2e-8818-f4a2af125182 | 5373 | Did not recover (≥120s of zero bytes when log was captured; user had to ESC) |

The 51.8s and 67.6s recovery times look like they line up with a 60s server-side internal timeout/retry boundary.

Representative log excerpt (stall # 4, the one that didn't recover)

2026-04-26T19:45:26.603Z [DEBUG] [API REQUEST] /v1/messages x-client-request-id=28380ec8-29ba-4e2e-8818-f4a2af125182 source=repl_main_thread
2026-04-26T19:45:28.731Z [DEBUG] Stream started - received first chunk
2026-04-26T19:45:42.866Z [DEBUG] (last activity from this stream)
2026-04-26T19:45:57.864Z [WARN] [Stall] stream_idle_partial lastChunkAgeMs=15000 bytesTotal=5373 idleDeadlineMs=900000
2026-04-26T19:46:12.863Z [WARN] [Stall] stream_idle_partial lastChunkAgeMs=30000 bytesTotal=5373 idleDeadlineMs=900000
2026-04-26T19:46:42.864Z [WARN] [Stall] stream_idle_partial lastChunkAgeMs=60001 bytesTotal=5373 idleDeadlineMs=900000
2026-04-26T19:47:42.864Z [WARN] [Stall] stream_idle_partial lastChunkAgeMs=120000 bytesTotal=5373 idleDeadlineMs=900000

bytesTotal=5373 is unchanged across all four warnings — i.e. zero bytes received during the 2-minute window. No message_stop, no error event, no TCP-level disconnect.

Representative log excerpt (stall # 1, which recovered)

2026-04-26T19:25:27.805Z [DEBUG] [API REQUEST] /v1/messages x-client-request-id=721d0de1-200f-422e-b7c8-c90dd211f62c source=repl_main_thread
2026-04-26T19:25:30.445Z [DEBUG] Stream started - received first chunk
2026-04-26T19:25:46.135Z [WARN] [Stall] stream_idle_partial lastChunkAgeMs=15001 bytesTotal=737 idleDeadlineMs=900000
2026-04-26T19:26:13.288Z [WARN] [Stall] stream_idle_partial lastChunkAgeMs=14999 bytesTotal=773 idleDeadlineMs=900000
2026-04-26T19:26:22.912Z [WARN] Streaming stall detected: 51.8s gap between events (stall #1)
2026-04-26T19:26:43.288Z [WARN] [Stall] stream_idle_partial lastChunkAgeMs=15000 bytesTotal=17424 idleDeadlineMs=900000
2026-04-26T19:26:48.862Z [WARN] Streaming completed with 1 stall(s), total stall time: 51.8s

Note that bytesTotal only moves from 737 → 773 between the first two warnings (a trickle), then jumps to 17424 after the gap is over. That suggests the server held back roughly 16KB of generated tokens for ~50s before flushing.

What's not happening

  • Not the client: the client is doing the right thing — [Stall] stream_idle_partial fires every 15s while waiting, no read errors are logged.
  • Not the network: the connection stays open the whole time. TCP isn't dropping. No proxy involved (ANTHROPIC_CUSTOM_HEADERS=false, no Authorization override).
  • Not the hooks/tools: tool_dispatch_* events all complete normally and quickly. Hooks aren't wedged. No tool exceeds even a second.
  • Not the local environment: bash/LSP/MCP all healthy. The 6 unauthorized claude.ai MCP connectors and the one Mermaid-Chart 502 at startup are unrelated and complete in milliseconds.
  • Not subagents: ~30+ requests with source=agent:builtin:Explore or source=agent:builtin:Plan in the same session, none stalled. Only source=repl_main_thread requests are affected.
  • Not context-size: most recent stall fired with autocompact: tokens=73852 threshold=167000 — well under any threshold.

What I think is happening (speculation)

A server-side issue specific to streaming on the path used by main-thread Claude Code requests. The pattern (early-token stall, ~60s internal recovery boundary, never affects subagents) is consistent with an overloaded/restarting inference worker holding generated tokens before flushing them downstream — and occasionally dropping the rest.

Session metadata for cross-reference

  • Session ID: b3ad7516-35cd-47cb-9e98-6916ee362882
  • Project: medium-sized git repo (~121 tracked files), no LSP servers active
  • Plugins enabled: feature-dev, code-review, ralph-loop, playwright (MCP), commit-commands, security-guidance, pr-review-toolkit, claude-code-setup, superpowers-extended-cc
  • attribution header x-anthropic-billing-header: cc_version=2.1.119.9c7; cc_entrypoint=cli

Happy to share the full debug log directly with Anthropic engineering if useful.

View original on GitHub ↗

This issue has 14 comments on GitHub. Read the full discussion on GitHub ↗