claude-code - 💡(How to fix) Fix [BUG] Cowork Edit/Write tools silently clamp final file size to pre-edit size on FUSE-mounted workspace (deterministic repro) [1 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
anthropics/claude-code#52581Fetched 2026-04-24 06:03:19
View on GitHub
Comments
1
Participants
2
Timeline
5
Reactions
0
Timeline (top)
labeled ×4commented ×1

In Claude Cowork mode (Claude Desktop), the Edit and Write tools silently clamp the final on-disk file size to the pre-edit file size, regardless of the size of the new content.

  • When the edit would grow the file, tail bytes are silently dropped.
  • When the edit would shrink the file, the trailing space is filled with null bytes (\x00).

No error or warning is emitted; both tools report "updated successfully."

This is distinct from (but related to) the cache-coherency bug tracked in #42520 and the non-atomic-config-write bug in #28809 / #29250. This issue is deterministic and reproducible on a fresh session with a single tool call, ruling out concurrency or session-boundary races.

Severity: data-destroying. Silent corruption of source files that Claude reports as successful writes. Affected users only discover the corruption when downstream compile/test fails — or worse, when a file compiles but is missing functionality.

Error Message

No error or warning is emitted; both tools report "updated successfully." 2. If for any reason the on-disk result does not match the intended content length, the tool should return an explicit error to the agent. Silent clamping — with the tool reporting "updated successfully" — is the worst possible failure mode because it poisons downstream Edit chains that build on the assumption the last write was correct. 2. Short-term: Return an explicit error on any write where final file size does not match intended content length. Do not trust the syscall sequence to have completed correctly without verification.

Error Messages/Logs

No error messages — that is the bug. The tool reports "updated successfully" in all cases. The first original_size bytes of the intended result match exactly. The last 109 bytes are dropped with no error.

  • #27896 — Silent failure when model output is truncated before tool call emission (different mechanism, similar class: silent failures with no error)

Root Cause

  1. If for any reason the on-disk result does not match the intended content length, the tool should return an explicit error to the agent. Silent clamping — with the tool reporting "updated successfully" — is the worst possible failure mode because it poisons downstream Edit chains that build on the assumption the last write was correct.

Fix Action

Fix / Workaround

Current workaround

Avoid the Edit and Write tools for any size-changing operation on FUSE-mounted workspace paths. Use bash (sed -i, heredocs, cat >>) instead. Pair with a downstream audit script that py_compiles every script and detects null-byte padding before any pipeline run. This is a load-bearing workaround — users shouldn't need it.

Code Example

No error messages — that is the bug. The tool reports "updated successfully" in all cases.

Byte-level evidence below.

===== Test 2 (shrink case), tail hex dump of the corrupted file =====

00000020:  206d 6174 6368 6564 202f 2074 6f74 616c  ' matched / total'
00000030:  2c20 656c 6170 7365 6429 0a0a 0a69 6620  ', elapsed)...if '
00000040:  5f5f 6e61 6d65 5f5f 203d 3d20 225f 5f6d  '__name__ == "__m'
00000050:  6169 6e5f 5f22 3a0a 2020 2020 6d61 696e  'ain__":.    main'
00000060:  2829 0a00 0000 0000 0000 0000 0000 0000  '()..............'
00000070:  0000 0000 0000 0000 0000 0000 0000 0000  '................'
00000080:  0000 0000                                '....'

Note `main()\n` followed by 28 null bytes (0x00) to fill to the original size.

===== Test 1 (grow case), MD5 verification =====

md5sum of first 95063 bytes of expected (bash-computed) result:
    e0c4d80243911fdb92ea635b6eb67b7d
md5sum of actual file after Edit tool call:
    e0c4d80243911fdb92ea635b6eb67b7d

The first `original_size` bytes of the intended result match exactly. The last 109 bytes are dropped with no error.
RAW_BUFFERClick to expand / collapse

Preflight Checklist

  • I have searched existing issues and this hasn't been reported yet
  • This is a single bug report (please file separate reports for different bugs)
  • I am using the latest version of Claude Code

What's Wrong?

Summary

In Claude Cowork mode (Claude Desktop), the Edit and Write tools silently clamp the final on-disk file size to the pre-edit file size, regardless of the size of the new content.

  • When the edit would grow the file, tail bytes are silently dropped.
  • When the edit would shrink the file, the trailing space is filled with null bytes (\x00).

No error or warning is emitted; both tools report "updated successfully."

This is distinct from (but related to) the cache-coherency bug tracked in #42520 and the non-atomic-config-write bug in #28809 / #29250. This issue is deterministic and reproducible on a fresh session with a single tool call, ruling out concurrency or session-boundary races.

Severity: data-destroying. Silent corruption of source files that Claude reports as successful writes. Affected users only discover the corruption when downstream compile/test fails — or worse, when a file compiles but is missing functionality.

Environment

  • Platform: Claude Desktop, Cowork mode (not Claude Code CLI), Windows 11
  • Mount layer: virtiofs → bindfs (v1.14.7, rw,nosuid,nodev,relatime,user_id=0,group_id=0,default_permissions,allow_other)
  • Reproduced on: both plain fuse (virtiofs passthrough, session outputs/ directory) and fuse.bindfs (user-selected workspace folder). Not mount-specific.
  • Tools affected: Edit tool, Write tool
  • Tools NOT affected: bash sed -i, bash cat > file << EOF, bash cp — proven clean in control tests

Impact in practice

One user working on a data pipeline project has repeatedly lost working code to this bug across multiple sessions:

  • 6 scripts corrupted simultaneously at session start — each clamped to its own prior size. Included small files (72-line _paths.py, 3191 bytes) and large (2000-line enrich.py, 85000 bytes). Pattern is size-independent.
  • Mid-session enrich.py truncation at byte 83751 — after an Edit that grew a function by ~114 lines. Exactly matches the "size clamped to pre-edit size" signature.
  • standardize.py with 47 null bytes at EOF — textbook shrink-case signature.

A downstream _audit.py script now catches these via py_compile + null-byte detection, but by then the damage is done: edit chains were built on corrupt files, and recovery requires reconstructing dropped tail content from prior-session Reads.

What Should Happen?

Expected behavior

  1. Edit and Write tool calls should produce a file whose size matches the actual intended content length. The Edit tool already knows the full new content from its new_string parameter; the Write tool knows the content length. Neither should end up shorter than the content they were given.

  2. If for any reason the on-disk result does not match the intended content length, the tool should return an explicit error to the agent. Silent clamping — with the tool reporting "updated successfully" — is the worst possible failure mode because it poisons downstream Edit chains that build on the assumption the last write was correct.

Requested fixes

  1. Short-term: Make the Edit and Write tools perform atomic writes (write to temp file → fsyncrename). On Windows NTFS, same-volume rename is atomic and would prevent partial writes. This is the same pattern proposed for the .claude.json corruption in #28809 / #29250.

  2. Short-term: Return an explicit error on any write where final file size does not match intended content length. Do not trust the syscall sequence to have completed correctly without verification.

  3. Longer-term: Audit all filesystem operations across Cowork's mount layer for similar patterns. The fact that git init on the same mount produces a 54-byte all-whitespace config file suggests FUSE-layer issues beyond these two specific tools.

Error Messages/Logs

No error messages — that is the bug. The tool reports "updated successfully" in all cases.

Byte-level evidence below.

===== Test 2 (shrink case), tail hex dump of the corrupted file =====

00000020:  206d 6174 6368 6564 202f 2074 6f74 616c  ' matched / total'
00000030:  2c20 656c 6170 7365 6429 0a0a 0a69 6620  ', elapsed)...if '
00000040:  5f5f 6e61 6d65 5f5f 203d 3d20 225f 5f6d  '__name__ == "__m'
00000050:  6169 6e5f 5f22 3a0a 2020 2020 6d61 696e  'ain__":.    main'
00000060:  2829 0a00 0000 0000 0000 0000 0000 0000  '()..............'
00000070:  0000 0000 0000 0000 0000 0000 0000 0000  '................'
00000080:  0000 0000                                '....'

Note `main()\n` followed by 28 null bytes (0x00) to fill to the original size.

===== Test 1 (grow case), MD5 verification =====

md5sum of first 95063 bytes of expected (bash-computed) result:
    e0c4d80243911fdb92ea635b6eb67b7d
md5sum of actual file after Edit tool call:
    e0c4d80243911fdb92ea635b6eb67b7d

The first `original_size` bytes of the intended result match exactly. The last 109 bytes are dropped with no error.

Steps to Reproduce

Deterministic reproduction recipe

Setup

  1. Start a fresh Claude Cowork session on Windows.
  2. Select a workspace folder on the host (mounted as bindfs into the session).
  3. Place any existing text file of known size in the workspace. Tests below use a 95063-byte Python file (2162 lines), but the bug is size-independent.
  4. Record original size and md5sum via bash (stat -c %s <file> and md5sum <file>).

Test 1 — Edit that grows the file

Edit tool call:

file_path: <absolute/path/to/file>
old_string: "<first 60 bytes of file...>"
new_string: "<first 60 bytes of file...>\n# MARKER_ADDING_22_BYTES"
  • Expected: file grows by 22 bytes (95063 → 95085).
  • Actual: file remains at 95063 bytes exactly. The last 22 bytes of the correctly-modified content are silently dropped. File ends mid-statement.

Test 2 — Edit that shrinks the file

Edit tool call:

file_path: <absolute/path/to/file>
old_string: "<60-byte original string...>"
new_string: "<27-byte replacement>"
  • Expected: file shrinks by 33 bytes (95063 → 95030).
  • Actual: file remains at 95063 bytes. Correct content up to byte 95030, then null bytes (\x00) padding to byte 95063.

Test 3 — Write that grows a small target file

Target: existing 46-byte file. Write call with 500+ bytes of new content.

  • Expected: file replaced with 500+ bytes.
  • Actual: file is exactly 46 bytes. Contains only the first 46 bytes of the new content. Everything else dropped.

Test 4 — Bash control (proves mount layer is not the sole cause)

sed -i 's/<old>/<new>/' <same-file>

Produces correct file size every time on the same mount. No truncation, no null padding. This isolates the bug to the Edit / Write tool implementation, not the FUSE / bindfs layer beneath.

All four tests repro in a single session with a single tool call each — no compaction, no session boundary, no concurrent host-side editing.

Claude Model

Opus

Is this a regression?

I don't know

Last Working Version

No response

Claude Code Version

N/A — Claude Desktop, Cowork mode (not Claude Code CLI). This bug is in the Cowork desktop client, filed here because related Cowork bugs (#42520, #38993) are tracked in this repo.

Platform

Other

Operating System

Windows

Terminal/Shell

PowerShell

Additional Information

Note on template mismatch

This bug is in Claude Desktop Cowork mode, not Claude Code CLI. The Bug Report template has CLI-specific required fields (Claude Code Version, Terminal/Shell). I've filled them best-effort (N/A for version, Other for platform/terminal) since there does not appear to be a Cowork-specific issue form and related Cowork bugs (#42520 FUSE cache coherency, #38993 virtiofs truncation) are tracked in this repo.

Suggested root cause

The signature — "final file clamped to pre-edit size, tail dropped or zero-padded" — is consistent with a write pattern that:

  1. Opens the file with O_WRONLY | O_TRUNC (size → 0).
  2. Writes the new content.
  3. Calls ftruncate(fd, pre_edit_size) with the wrong size argument — passing the pre-edit length instead of the post-write position.

Alternatively, the Edit/Write implementation may be using a fixed-size buffer sized to the pre-edit length and writing only that many bytes. Either way, the fix is to use the new content's actual length — and ideally adopt the standard safe pattern: write to a temp file, fsync, rename() into place (same as proposed in #28809 / #29250).

Cross-references

  • #42520 — Cowork FUSE Mount Cache Coherency Failure on Host-Side File Writes (same FUSE layer, related class of bug)
  • #28809 — .claude.json corrupted (Unexpected EOF) — non-atomic config writes
  • #29250 — Non-atomic writes to .claude.json cause file corruption
  • #38993 — Cowork virtiofs FUSE serves truncated/stale files
  • #23053 — VSCode extension freezes when generating large file content for Write/Edit
  • #27896 — Silent failure when model output is truncated before tool call emission (different mechanism, similar class: silent failures with no error)

Current workaround

Avoid the Edit and Write tools for any size-changing operation on FUSE-mounted workspace paths. Use bash (sed -i, heredocs, cat >>) instead. Pair with a downstream audit script that py_compiles every script and detects null-byte padding before any pipeline run. This is a load-bearing workaround — users shouldn't need it.

Additional environment details

  • Bindfs mount options: rw,nosuid,nodev,relatime,user_id=0,group_id=0,default_permissions,allow_other
  • Bindfs version: 1.14.7
  • Session's own outputs/ directory (plain virtiofs, not bindfs) also exhibits the bug — this is not a bindfs-specific issue
  • Bash writes on the exact same paths are always correct size — isolates the bug to the Edit/Write tool implementations

extent analysis

TL;DR

The most likely fix for the issue is to implement atomic writes for the Edit and Write tools, ensuring that the file size matches the intended content length, and returning an explicit error if the write operation fails.

Guidance

  • The issue is likely caused by the Edit and Write tools using a fixed-size buffer or an incorrect ftruncate call, resulting in the file being clamped to its pre-edit size.
  • To fix this, the tools should be modified to use the new content's actual length and adopt the standard safe pattern of writing to a temp file, fsync, and then rename() into place.
  • The Edit and Write tools should also be updated to return an explicit error if the final file size does not match the intended content length.
  • Additionally, auditing all filesystem operations across Cowork's mount layer for similar patterns can help identify and fix related issues.

Example

# Pseudo-code example of atomic write
def atomic_write(file_path, content):
    temp_file_path = file_path + '.tmp'
    with open(temp_file_path, 'w') as temp_file:
        temp_file.write(content)
    os.fsync(temp_file.fileno())
    os.rename(temp_file_path, file_path)

Notes

  • The issue is specific to the Edit and Write tools in Claude Desktop Cowork mode and does not affect the Claude Code CLI.
  • The bug is deterministic and reproducible, making it easier to test and fix.
  • The suggested workaround of using bash commands instead of the Edit and Write tools can help mitigate the issue, but a proper fix is necessary to ensure data integrity.

Recommendation

Apply the workaround of using bash commands for size-changing operations and implement atomic writes for the Edit and Write tools to prevent data corruption and ensure accurate file sizes.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

FAQ

Expected behavior

  1. Edit and Write tool calls should produce a file whose size matches the actual intended content length. The Edit tool already knows the full new content from its new_string parameter; the Write tool knows the content length. Neither should end up shorter than the content they were given.

  2. If for any reason the on-disk result does not match the intended content length, the tool should return an explicit error to the agent. Silent clamping — with the tool reporting "updated successfully" — is the worst possible failure mode because it poisons downstream Edit chains that build on the assumption the last write was correct.

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING