Edit/Write tool results delayed 50-600s while Read stays at 0.1s; no local cause found after 10 exclusions
Environment: Claude Code 2.1.218 (also seen on 2.1.220), macOS Darwin 25.5.0, native install ~/.local/share/claude/versions/. Private git repo, ~970 tracked files. permissions.defaultMode: "auto".
Symptom
An Edit or Write call returns its tool result only after 50-600 seconds. The file is written long before that — only the result is missing. The session appears frozen: no output, no error. It then resolves by itself.
Measured from transcripts (~/.claude/projects/<proj>/*.jsonl): tool_use.id matched to tool_result.tool_use_id, difference of timestamp fields.
The break is a step change on a single day, on an unchanged binary
┌────────┬─────────────┬─────┬────────┬──────┬──────┐
│ Day │ Version │ n │ median │ max │ >30s │
├────────┼─────────────┼─────┼────────┼──────┼──────┤
│ Jul 24 │ 2.1.218 │ 157 │ 0.1s │ 0.1s │ 0 │
├────────┼─────────────┼─────┼────────┼──────┼──────┤
│ Jul 25 │ 2.1.219 │ 207 │ 0.1s │ 12s │ 0 │
├────────┼─────────────┼─────┼────────┼──────┼──────┤
│ Jul 26 │ 2.1.220/218 │ 112 │ 2.7s │ 582s │ 31 │
├────────┼─────────────┼─────┼────────┼──────┼──────┤
│ Jul 27 │ 2.1.218 │ 6 │ 415s │ 601s │ 4 │
├────────┼─────────────┼─────┼────────┼──────┼──────┤
│ Jul 28 │ 2.1.218 │ 14 │ 55s │ 345s │ 8 │
└────────┴─────────────┴─────┴────────┴──────┴──────┘
2.1.218 ran 157 writes at median 0.1s on Jul 24 and shows median 55s on Jul 28 — same binary, same machine, same repo. Within Jul 26 the break falls between 09:55 and 10:18 UTC. Two values sit at 600.5s and 601s, which looks like a 10-minute timeout with retry rather than scatter.
Only the write path is affected
┌───────┬────────┬────────┬────────────────┬────────┬────────┐
│ Tool │ Jul 24 │ Jul 25 │ Jul 26 │ Jul 27 │ Jul 28 │
├───────┼────────┼────────┼────────────────┼────────┼────────┤
│ Edit │ 0.1s │ 0.1s │ 3.6s (max 582) │ 600s │ 55s │
├───────┼────────┼────────┼────────────────┼────────┼────────┤
│ Write │ 0.1s │ 0.1s │ 2.6s (max 424) │ 50s │ 290s │
├───────┼────────┼────────┼────────────────┼────────┼────────┤
│ Read │ 0.1s │ 0.1s │ 0.1s (max 5) │ 0.1s │ 0.1s │
├───────┼────────┼────────┼────────────────┼────────┼────────┤
│ Bash │ 2.3s │ 2.6s │ 3.5s │ 3.5s │ 2.7s │
└───────┴────────┴────────┴────────────────┴────────┴────────┘
Where the stall sits
13:58:53.332 tool_use: Edit
13:58:53.741 hook completed (+0.4s)
13:59:58.216 tool_result (+64.5s of nothing)
No transcript entry in between. Records of a fast and a stalled call are structurally identical (same keys in tool_use, tool_result, toolUseResult).
Denied calls return immediately — a classifier-blocked Edit took 18.3s, pure decision time with no file work. So the stall is behind the permission decision.
Affected targets are files inside any git working tree — reproduced in two different repos on the same machine (project repo and ~/.claude, which is itself a working tree with its own remote). A write into a non-versioned scratchpad completed in 6s.
Excluded, each with a measurement
┌───────────────────┬─────────────────────────────────────────────┬───────────────────────────────────────────────────────┐
│ Candidate │ Measurement │ Result │
├───────────────────┼─────────────────────────────────────────────┼───────────────────────────────────────────────────────┤
│ Checkpointing / │ set fileCheckpointingEnabled: false; the │ flag took effect, stall remained (64.9s on the same │
│ file-history │ file-history-delta transcript entry │ file that took 54.5/55.3s) │
│ │ disappeared │ │
├───────────────────┼─────────────────────────────────────────────┼───────────────────────────────────────────────────────┤
│ auto-mode │ switched to acceptEdits, same edit, same │ 84.0s — no improvement │
│ classifier │ file │ │
├───────────────────┼─────────────────────────────────────────────┼───────────────────────────────────────────────────────┤
│ Hooks │ all repo hooks with real stdin payload │ 20-46ms; for the specific stalled file 0.06s / 0.02s │
├───────────────────┼─────────────────────────────────────────────┼───────────────────────────────────────────────────────┤
│ Network │ git ls-remote both repos, gh api, curl to │ all < 0.8s │
│ │ api.anthropic.com and github.com │ │
├───────────────────┼─────────────────────────────────────────────┼───────────────────────────────────────────────────────┤
│ Git │ git status --porcelain both repos │ 0.03s / 0.02s │
├───────────────────┼─────────────────────────────────────────────┼───────────────────────────────────────────────────────┤
│ Concurrent │ max simultaneously active sessions per day │ 1 through Jul 27 │
│ sessions │ │ │
├───────────────────┼─────────────────────────────────────────────┼───────────────────────────────────────────────────────┤
│ │ git log -S per key in │ │
│ Config change │ ~/.claude/settings.json (it is version │ none in the Jul 26 09:55-10:18 UTC window │
│ │ controlled) │ │
├───────────────────┼─────────────────────────────────────────────┼───────────────────────────────────────────────────────┤
│ file-history │ du │ 30MB, largest single file 168KB │
│ store size │ │ │
├───────────────────┼─────────────────────────────────────────────┼───────────────────────────────────────────────────────┤
│ Target file size │ correlation size/duration, n=102 │ r = 0.003 │
├───────────────────┼─────────────────────────────────────────────┼───────────────────────────────────────────────────────┤
│ │ │ r = 0.786 / 0.129 / 0.055 / 0.373 / -0.318 — │
│ Transcript │ correlation byte offset/duration per day │ inconsistent, negative on the last day. Control: 60 │
│ context size │ │ writes at 6-12MB context on Jul 23-25 sat at median │
│ │ │ 0.1s │
├───────────────────┼─────────────────────────────────────────────┼───────────────────────────────────────────────────────┤
│ Stop-hook chain / │ run timestamps vs stall windows │ no run inside a stall window │
│ sync scripts │ │ │
└───────────────────┴─────────────────────────────────────────────┴───────────────────────────────────────────────────────┘
What I could not do
Reproduce on a second machine or a different network path. Everything locally configurable was toggled and measured without effect. Rare instances of this predate the step change (Jun 21: 6 cases max 126s; Jun 28: 12 cases; Jul 9: max 237s) — an explanation needs to carry both the old background rate and the jump.
Raw transcripts with timestamps available on request.