Server withholds stream bytes after accepting request — frequent slow-first-byte and 180s idle-timeout aborts (2.1.157, Opus 4.8)

Open 💬 5 comments Opened Jun 7, 2026 by daira

Summary

On Claude Code CLI 2.1.157 (model claude-opus-4-8), the server frequently accepts a /v1/messages request (request-id is issued) and then sends no bytes for tens-to-hundreds of seconds. When the silence is <180s the turn returns slow; when it reaches the client byte-watchdog's 180000ms idle deadline the stream is aborted and retried. In one ~3-hour session this produced 25 hard aborts plus 12 recovered-but-slow turns. The evidence below indicates a server-side cause (stream start / next-chunk is delayed upstream), independent of context size, prompt-cache TTL, usage-credits/fast-mode, and --debug.

All timestamps in this report are UTC.

Environment

  • Claude Code 2.1.157 (CLI, native install; claude --version2.1.157). The attribution header reports cc_version=2.1.157.ac1 and 2.1.157.6d8 across two launches of the same binary (no auto-update occurred between them) — the suffix appears to be a config/feature-flag fingerprint, not a separate build. Both reproduce the issue.
  • Model claude-opus-4-8, first-party endpoint (not Bedrock/Vertex)
  • Linux; direct connection (no corporate proxy)
  • Installed via the third-party Nix package sadjow/claude-code-nix (not the official installer). Noting this for completeness — but the symptom is server-side (request accepted, then no bytes; see request-ids below), which client packaging cannot cause. Happy to reproduce on an official install if useful.

Signature — two forms of the same behavior

  1. Pre-first-byte stall (bytesTotal=0): no first chunk for 30–87s. Recovers if it arrives before 180s; otherwise the byte-watchdog fires.
  2. Mid-decode stall: server emits ~0.6–57 KB, then goes silent ≥180s → Streaming idle timeout (byte-level) … aborting streamapi_timeout after retries → retry (which re-prefills the whole prompt).

Recovered pre-first-byte stall (request 2b3939ca-acc7-4bd9-8126-2abde5fbd874, UTC):

17:47:54  [API REQUEST] /v1/messages x-client-request-id=2b3939ca-…
17:48:14  [Stall] stream_idle_partial lastChunkAgeMs=14999 bytesTotal=0 idleDeadlineMs=180000
17:48:24  Slow first byte: no stream chunk 30.0s after request sent (attempt 1)
17:48:59  [Stall] stream_idle_partial lastChunkAgeMs=59999 bytesTotal=0
17:49:06  Stream started - received first chunk
17:49:06  [API:timing] first byte after 71789ms      ← recovered at 71s

Hard abort (byte-watchdog at the 180s deadline, UTC):

14:57:00  [byte-watchdog] firing: idle=180000ms late=0ms errored=false bodyReadPending=true
14:57:00  [ERROR] Streaming idle timeout (byte-level): stream idle: no bytes for 180000ms, aborting stream
14:57:00  [ERROR] API api_timeout after retries: Stream idle timeout - partial response received

What this is NOT (ruled out with evidence)

| Hypothesis | Verdict | Evidence |
|---|---|---|
| Large context (~900k tokens) | excluded | 18 of 25 aborts occurred after a /compact, on turns whose neighbors had normal ~2.5s TTFB |
| ENABLE_PROMPT_CACHING_1H | excluded | reproduced with the flag off (default 5m TTL): 71789ms TTFB + stalls |
| Usage-credits / fast-mode | excluded | first stall at 14:50 UTC preceded enabling credits (15:07/15:10 UTC); abort cadence unchanged after |
| --debug / --debug-file | excluded | API Error: Stream idle timeout was seen in the UI before debug was enabled; and the [Stall] watchdog timers fire on-schedule (15/30/60/120s) during a stall, proving the client event loop is not blocked |

Decisive tell: time-to-first-byte of **66–71s on low-context turns** (e.g. 17:08–17:10 UTC, and the post-resume turn above). A small prompt cannot take that long to prefill — the server is withholding the first token. bodyReadPending=true errored=false confirms the client is healthily awaiting bytes that never arrive.

Frequency (one session, 14:49–17:52 UTC)

  • 25 hard aborts (byte-watchdog / request-aborted)
  • 12 additional turns with TTFB > 30s that recovered before 180s
  • normal turns: ~2–5s TTFB

Request-ids for server-log lookup (UTC)

All 25 aborts, with the bytes received before the stall (0 = pre-first-byte, else mid-decode byte count):

14:57:00  3687e426-d315-40f4-b4c5-4417e43495b4  bytes=7639
15:04:53  48675c2e-e9d0-4c70-abad-c9f271adba26  bytes=860
15:14:36  50a87a9f-bf77-4b1f-8e73-9c9f63ba17cf  bytes=859
15:21:21  1cfb6366-8a8f-4128-8e54-21f3a1f0ac91  bytes=0
15:31:01  28471286-6ef1-4b54-8e42-928547c5f160  bytes=0
15:36:39  97cd0cff-0ef0-40c3-ac0f-a177dc37f388  bytes=56889
15:43:22  20c85099-430e-4bd5-9786-7e97bae8aabd  bytes=991
15:50:53  5dca0dea-a363-484b-a841-c757e9997418  bytes=2068
16:00:37  1fcb1f92-aca3-4086-96ec-31304f88f70b  bytes=1603
16:03:57  8dbc52fc-2e74-412f-bb98-645a6a5ea1ba  bytes=1603
16:07:44  e83b19c4-0f7b-4863-a740-e3c044d4c543  bytes=1472
16:11:54  afab8219-31b4-4149-b2c0-1dd628a90579  bytes=4586
16:15:06  e51ad0b8-64b5-4bbc-a46a-05921ff52563  bytes=1604
16:25:23  8f8ab34b-5181-4423-9fc8-ab6b9ed992d0  bytes=1621
16:31:09  53ba085a-ecde-4541-9019-b0fa69b46b0f  bytes=9185
16:35:02  dfdd4924-136b-415b-8818-201766b745be  bytes=839
16:38:36  167a71e2-d5e8-43cf-8d0a-3e819f527a2c  bytes=2377
16:43:28  bb97181e-38d6-41c3-ba84-34fe2d031dd6  bytes=4222
16:48:08  8b1e9c72-9aab-4b5e-8e59-f4ea499e91bc  bytes=2389
16:51:48  73eb245f-6144-425f-a481-76ae76f4598b  bytes=1459
17:00:54  233eb958-1fd7-4a23-bf63-c71c420f313e  bytes=1158
17:01:03  83fe437f-8e01-42d5-805e-b2548b1b7ccc  bytes=1158
17:04:29  c5477f86-4182-4a50-8248-f080b95b749a  bytes=2986
17:17:30  f253e4eb-bf11-4126-9a58-ee99cc7ea8cd  bytes=1475
17:47:21  b780daea-1d1c-47e8-8efe-c44e871e9416  bytes=658

Recovered-but-slow example: 2b3939ca-acc7-4bd9-8126-2abde5fbd874 (TTFB 71789ms, caching flag off).

Ask

Please trace, for these request-ids, why stream_start (and subsequent chunks) are delayed or never emitted server-side. From the client side everything indicates upstream queueing/stalling rather than a client, network, context, or configuration cause. Independently, it would help to expose the byte-watchdog idle deadline as a configurable value (it currently appears fixed at 180000ms).

Likely related

#49716, #53730, #49619, #46987, #47841, #37080 — same "stream idle timeout / partial response" family.

View original on GitHub ↗

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