Reconsider #26729: auto-resume after mid-response stream drop (detection already ships in v2.1.186)

Resolved 💬 2 comments Opened Jun 30, 2026 by asror-z Closed Jul 4, 2026

Reconsider #26729 — auto-resume after a mid-response stream drop (detection already ships)

Summary

API Error: Connection closed mid-response ends the turn dead. In auto-accept / headless runs this forces a human back to the keyboard to type continue, which defeats unattended operation.

The detection half already exists in the CLI (v2.1.186) — only the re-issue half is missing:

| Layer | Status |
|---|---|
| 1. Detect the drop (byte/stream watchdog, abort cleanly) | ✅ ships (CLAUDE_ENABLE_BYTE_WATCHDOG on; CLAUDE_ENABLE_STREAM_WATCHDOG forced on in daemon/bg) |
| 2. Preserve partial state | ✅ ships (keepPartialMessageOnAbort"The response above may be incomplete.") |
| 3. Auto-resume the interrupted turn | ❌ missing — user must manually continue |

Since detection + partial capture are already present, wiring the existing abort path into an automatic re-issue (with a "previous response was truncated; continue from the last completed step" marker so finished work isn't redone) closes the gap with little new machinery.

Observed env vars (undocumented; names/defaults may drift)

  • CLAUDE_ENABLE_BYTE_WATCHDOG (default on) — idle-byte abort; CLAUDE_BYTE_STREAM_IDLE_TIMEOUT_MS (~1ms–30min). Emits tengu_byte_watchdog_fired.
  • CLAUDE_ENABLE_STREAM_WATCHDOG (default off, forced on in bg/daemon) — SSE event-gap; deadline max(CLAUDE_STREAM_IDLE_TIMEOUT_MS, 300000). Emits tengu_streaming_stall.

Proposed bounded design

  1. Stream watchdog — already present; reuse it to abort the partial turn cleanly.
  2. Recovery snapshot — persist state up to the last complete message + the in-flight prompt; record completed tool calls (mutations like Edit/Bash must not be blindly re-run; read-only tools are safe to retry).
  3. Auto-resume — re-issue the interrupted turn, injecting a truncation marker so finished work isn't redone.

Suggested config:

  • CLAUDE_CODE_AUTO_RESUME_ON_DROP=1 — default on in headless/auto-accept, prompt in interactive.
  • CLAUDE_CODE_MAX_RESUME_ATTEMPTS=3 — bounded with backoff; give up gracefully with recovery instructions when exceeded.

Even layers 1 + 3 alone (clean detect + automatic re-issue) remove most of the babysitting burden in auto mode, without full mutation-aware recovery up front.

Local stopgap implemented in the meantime

A Stop hook (auto-resume-on-drop.mjs) that detects the drop signal in the transcript tail and re-issues the turn via decision:"block" with a "continue from the last completed step; don't re-run completed Edit/Bash mutations" marker, bounded by CLAUDE_CODE_MAX_RESUME_ATTEMPTS per session (resets on a clean turn, surfaces recovery guidance when exhausted). This proves layers 1+3 work end-to-end with no new CLI machinery.

View original on GitHub ↗

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