[BUG] Read tool serves cached payload after failed Write, masking on-disk corruption (no cache invalidation on write)
[BUG] Read tool serves cached payload after failed Write, masking on-disk corruption (no cache invalidation on write)
Background
Split-out from master ticket (54891). This issue isolates the Read cache trust-gap failure mode, which is arguably the most damaging of the 11 silent failures in the master ticket because it actively hides the other failures from the LLM.
Distinct from sibling issues:
- Not a
O_TRUNCwrite problem (split-01) - Not a UTF-8 boundary problem (split-02)
- Not a CRLF problem (split-04)
- Not a concurrency problem (split-05)
This is the detection-layer problem: even when one of the above write-layer bugs corrupts a file on disk, the in-session Read tool returns the intended payload from cache, so the LLM cannot self-detect the failure. Only out-of-band tools (xxd, Get-Content -AsByteStream, Python open('rb')) reveal that disk diverges from what Read reports.
Suspected root cause: the Read cache is keyed on (path, session) and populated from the LLM-visible payload of Write / Edit rather than re-reading disk after the OS reports the write complete. There's no cache invalidation step that compares expected_sha256 against disk_sha256.
Reproducer
Environment: Windows 11 + Cowork + virtiofs vault mount.
- Trigger any of the split-01 / split-02 / split-04 / split-05 failures (e.g.
Writea 2.6 KB payload over an existing 37 KB CJK file). - Immediately call
Readon the same path from Claude Code. - Observe:
Readreturns the intended 2.6 KB payload — no NULL bytes, no truncation. - Verify out-of-band:
``bash``
wc -c /vault/target.md
# 37000+ bytes, not 2600
python3 -c "d=open('/vault/target.md','rb').read(); print(len(d), d.count(b'\x00'))"
# Tail NULL padding present.
- The LLM continues with downstream edits, assuming
Readis authoritative; cascading corruption follows.
Expected behavior
- When
Write/Editreports success, the nextReadon that path must re-read from disk (one-cycle cache invalidation) and compare against the intended payload. - If
expected_sha256 != disk_sha256, the tool layer raises a "write verification failed" error rather than letting the nextReadsucceed. - Alternatively, expose a
verify_after_write(path, expected_sha256)MCP helper so the LLM can request explicit verification without authoring 9-item Python boilerplate. Readdocumentation should explicitly state whether it serves cache or disk — currently the contract is ambiguous.
Actual behavior
Read returns the cached intended payload regardless of whether the on-disk content matches. The LLM has no in-band signal that the write failed. By the time corruption is detected (next session, or when the user opens the file in Obsidian), multiple downstream edits have been made against the cached (phantom) state.
Concrete impact (2026-04-29 ~ 04-30): three vault core files (Memory.md, CLAUDE.md, 2026-04-29.md) simultaneously corrupted while the LLM was confident from Read that everything was fine; only clipboard-tier manual recovery from Obsidian app restored state. obsidian_create_or_update_note MCP returned success 4× for the same file; only manual NTFS mtime / sha256 check revealed the file had not changed.
Environment
- OS: Windows 11 (build 26100.x)
- Mount: virtiofs / Plan9 into Cowork sandbox
- Claude Code: 2.1.123
- MCP servers in play: Desktop_Commander, obsidian (FastMCP wrapper over Local REST API plugin)
Related
- Parent master ticket: (54891)
- Sibling splits: #54891-split-01, -02, -04, -05
- Adjacent: (54847) (silent stall — same trust-gap class: tool reports state that disagrees with reality)
Workaround (current)
Treat every vault Read as suspect; before relying on its output for downstream edits, run an out-of-band xxd | tail or python -c "print(open(p,'rb').read().count(b'\x00'))" via mcp__workspace__bash. Inflates every vault read-write loop by ~2× latency. Workable for solo users; not workable for any MSP / B2B use case at scale.
---
Cross-reference: split from closed master ticket #54891 (auto-closed as not_planned 2026-06-01 by github-actions[bot]; reproducible bugs persist). Also related to #64592 (Cowork VM service cluster). Submitted by dispatcher via REST API on behalf of the issue author (Claude Team subscription holder, IT MSP production use).
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗