[BUG] Edit tool silently misses some Edits in a rapid Edit + git mv + commit sequence (selective miss within same commit; refuted hypothesis 2 vs 1+3 still open)

Resolved 💬 1 comment Opened May 18, 2026 by tompahoward Closed Jun 17, 2026

What's Wrong?

Edit tool calls during a long agent flow (Edit + git mv + git add + commit, in rapid succession on tracked markdown files) returned "The file ... has been updated successfully." and Read showed the new content, but the committed content (verified via git show <SHA>:<path>) did NOT contain the Edits.

The pattern is selective, not whole-file:

  • Some Edits in the same close-succession sequence landed (a slice plan table, a ## Fix Released section, one investigation-task tick)
  • Other Edits in the same sequence did NOT land (Status field change, Priority line parenthetical removal, Effort wording update)

All Edits returned the same success acknowledgement; only git show revealed the misses.

What Should Happen?

  • Edit modifies the file on disk such that subsequent git add + commit ships the modified content
  • If Edit cannot complete (e.g., buffered state would be lost by a follow-on git mv), the tool surfaces an error rather than silently producing partial content
  • The selective-miss shape is the load-bearing signal: ANY hypothesis on the failure mode must explain how some Edits in a tight sequence land while others don't

Error Messages/Logs

NONE — Edit returned success on every call; Read after Edit confirmed the new content; only `git show <SHA>:<path>` after commit revealed that some Edits were missing from the tree.

Steps to Reproduce

The original failure mode was observed in production work on 2026-05-17. A controlled 7-test reproduction matrix run on 2026-05-18 (against /tmp/p011-repro.md with Claude Code 2.1.143) refuted the simplest hypothesis (Edit silent no-op on old_string mismatch) — every mismatch variant returned a loud, structured error:

| # | Variant | Result |
|---|---------|--------|
| 1 | Exact match (control) | Applied; success |
| 2 | old_string has trailing space file does not | "String to replace not found in file." |
| 3 | old_string has leading space file does not | "String to replace not found in file." |
| 4 | old_string entirely absent from file | "String to replace not found in file." |
| 5 | Case mismatch | "String to replace not found in file." |
| 6 | Non-unique old_string (2 matches) | "Found N matches… replace_all is false." |
| 7 | new_string == old_string (semantic no-op) | "No changes to make: old_string and new_string are exactly the same." |

So under isolated Edit-only conditions, the contract is honored. The unverified hypotheses are:

  1. git mv + Edit buffer-flush interaction — Edit modifies an in-memory buffer; subsequent git mv of the same path reads the on-disk state before the buffer flushes. (Tested only partially; selectivity-of-loss within the same commit doesn't fully fit this model.)
  2. Read-before-Edit staleness under concurrent process touch — between Read and Edit, some other process touched the file, and Edit applied against the stale snapshot. (Hard to instrument from the adopter side.)

A full reproduction would require: rapid Edit + git mv + git add + commit sequence on a tracked file inside a real repo, then git show <SHA>:<path> verification. Not run in iter 11 because there is no pre-existing regression to anchor it.

Affected Surface

Claude Code CLI, version 2.1.143 at iter 11 measurement time. Original P005 slice 2-4 work that surfaced the bug ran ~2026-05-17 on whatever Claude Code version was current then; not directly identifiable from session traces.

Evidence

  • Commit 80a8cb0 (2026-05-17, P005 slice 2-4 closure on downstream voder-mcp-hub): Edits to set Status: Verification Pending, remove the deferred-re-rate parenthetical, update the Effort wording, and tick investigation tasks did not all land. Verified via git show 80a8cb0:docs/problems/005-mcp-oauth-needed-for-claude-ai-web-and-ios.verifying.md — Status field still "Known Error"; deferred parenthetical still present; Effort wording was pre-slice "slice 1 of ~4" not post-slice "all 4 slices shipped"; investigation tasks unticked. The slice plan table and the entire ## Fix Released section DID land — selective miss within the same commit.
  • Commit 2d54d66 (same session, README-history closure): Edit added a closure fragment that did not land — committed file had 4 fragments, not the 5 intended.

Both detected by incidental re-read during follow-up work.

Versions

  • Local plugin: not applicable (this is a Claude Code CLI tool report, not a plugin)
  • Upstream package: @anthropic-ai/claude-code@2.1.143
  • Claude Code CLI: 2.1.143 (Claude Code)
  • Node: v22.17.1
  • OS: Darwin 25.3.0 x86_64

Related Issues

  • #53940Cowork Edit/Write tools silently truncate files via byte-conservation buffer cap (deterministic, fires at all file sizes). Different product (Cowork desktop research preview) and different mechanism (byte-conservation truncation, post-edit byte count == pre-edit byte count) but the same class of failure — Edit returns success while not writing the intended content. Triage may want to consider whether the two surfaces share an underlying buffer-management layer.

Cross-reference

Reported from voder-mcp-hub (downstream project):

  • Local P011: docs/problems/known-error/011-edit-tool-edits-silently-regressed-during-slice-2-4.md

Tracked locally as P011 in the downstream project's docs/problems/ directory.

Preflight Checklist

  • [x] I have searched existing issues; #53940 surfaces a related-but-distinct bug (different product, different mechanism) noted in Related Issues above
  • [x] This is a single bug report
  • [x] I am using the latest version of Claude Code (2.1.143)

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗