Tool results silently dropped in transit ('[Tool result missing due to internal error]' / indefinite 'Waiting')

Resolved 💬 2 comments Opened Jun 16, 2026 by toyuvalo Closed Jun 19, 2026

BUG REPORT — Claude Code silently drops completed tool results in transit

Product: Claude Code (interactive CLI/TUI)
Model: Opus 4.8 (claude-opus-4-8), Anthropic 1P API (not Bedrock/Vertex)
Platform: Windows 10 (native, not WSL) — PowerShell + Git-Bash tools
Severity: HIGH — silent, recurring, indistinguishable from a freeze, and it destroys the ability to trust long-running tasks.
Status: RECURRING for at least 4 consecutive days and counting. Still not fixed.

---

Impact: this costs real hours, repeatedly

This is not a curiosity. The defect burns hours across multiple days and keeps happening:

  • Unattended tasks do not finish. A long-running job left running unattended stalled mid-task when a single Write call dropped its result. The turn hung and the job sat half-done for hours until manually noticed. A whole unattended run, wasted.
  • Silent stalls, multiple times per day. The turn hangs on "Waiting" with no error, no spinner movement, nothing. You assume the model is thinking, wait, eventually give up, hit Esc, type "continue," and hope nothing was half-applied. Each event is several minutes of dead time, and there have been many — six-plus in a single day.
  • Ambiguous mutations require manual re-verification. When a Write/Edit/Bash result drops, you cannot tell whether the change landed. Some drops left no effect on disk (file missing, grep returns nothing); others did mutate. So every drop forces a manual ls/grep audit before retrying, or you risk double-applying. That tax, multiplied across days, is hours.
  • Users are forced to build external watchdogs just to detect that the harness lost a tool result. That should not be necessary.

The cumulative cost is hours of lost work, missed unattended deliverables, and erosion of any trust that a long task can be left running.

---

What the bug is

The harness intermittently loses a completed tool result in transit. The tool ran to completion locally (exit 0, side effects sometimes applied), but the result envelope never gets stitched back into the turn. It manifests three ways:

  1. Indefinite "Waiting" — the tool call hangs forever; only a manual Esc + "continue" breaks it.
  2. An explicit error placeholder: [Tool result missing due to internal error] — returned in place of real output for a command that could not have errored on its own (e.g. a tail of a log file).
  3. An empty/blank tool result.

The smoking gun is that error string: [Tool result missing due to internal error]. Tracing where it is emitted should lead straight to the defect.

---

Why existing mitigations do NOT catch this

The following are all live and none of them address a dropped completed tool result:

  • API_FORCE_IDLE_TIMEOUT=1 — turns on the model-stream idle watchdog (hardcoded ~5 min, not tunable). Only fires on model stream silence. A dropped tool result is a different casualty; the idle watchdog never sees it.
  • CLAUDE_CODE_MAX_RETRIES — retries the API request, not a dropped result.
  • API_TIMEOUT_MS, MCP_TOOL_TIMEOUT, MCP_TIMEOUT, async-agent stall timeout — none bound or recover a dropped tool-result delivery.

There is no client-side knob that recovers a dropped tool-result delivery. The documented troubleshooting only offers Ctrl+C / claude --resume, which is not acceptable for a recurring transport defect.

---

What was ruled OUT (to save investigation time)

Investigated empirically over several sessions. It is NOT:

  • Not the idle/thinking stallAPI_FORCE_IDLE_TIMEOUT=1 confirmed live in-process.
  • Not the hooks — all PreToolUse/PostToolUse hooks measured ~130 ms and run in parallel; the gate hook no-ops in ~5 ms. Ruled out directly.
  • Not ssh blocking — separately diagnosed and hardened with an ssh config (ConnectTimeout, BatchMode, keepalive). Different issue, already mitigated.
  • Not a synchronous Stop-hook — separately diagnosed and fixed with throttle + fire-and-forget. Different issue.

What remains is a genuine transport-layer drop of the tool_result block between the local tool runtime and the turn assembler (and/or the API round-trip carrying tool_results).

---

Pattern / frequency

  • Recurring multiple times per day, across at least 4 consecutive days.
  • Hits both single calls and parallel tool batches; both Bash and Edit/Write/Read — not purely a parallelism issue or a single-tool issue.
  • Clusters in time (several in a row, then clean) — consistent with intermittent API/transport instability.
  • Correlated with longer sessions and parallel tool-call batches (one of N siblings drops). Larger context = bigger payloads = higher hit rate.

---

Requested fixes (priority order)

  1. Root-cause the dropped tool_result delivery. Trace local tool runtime -> turn assembler -> API round-trip. Find every place [Tool result missing due to internal error] can be emitted and why.
  2. Built-in auto-recovery. When a tool_use has no tool_result after a configurable timeout, the harness must automatically re-request / re-deliver the result, or cleanly abort+retry the turn — never hang on "Waiting" indefinitely.
  3. Make tool-result delivery idempotent/retryable, independent of the model-stream idle watchdog, with a per-call delivery ack / idempotency token so the model can know with certainty whether a dropped tool actually executed (today that is ambiguous and dangerous for mutating calls).
  4. Surface it visibly. Show a "tool result lost — retrying..." state instead of a silent hang.
  5. Harden long/unattended sessions specifically against this class so unattended tasks complete.

---

Repro notes

Not deterministically reproducible (transport-timing dependent). Higher hit-rate in long sessions with parallel tool batches on the Anthropic 1P API, Windows native. Likely related to upstream streaming issues (e.g. GitHub #53328, #25979). Session logs and exact timestamps available on request.

---

Bottom line

A silent, recurring, multi-day, time-stealing transport bug that no documented setting can fix and that users are currently holding together with homemade watchdogs. The easy explanations have been ruled out. Please prioritize a real fix: a retryable, ack'd, auto-recovering tool-result delivery path.

View original on GitHub ↗

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