claude-code - 💡(How to fix) Fix [Bug] Edit tool silently truncates files after multiple block replacements [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#52881Fetched 2026-04-25 06:18:23
View on GitHub
Comments
1
Participants
2
Timeline
6
Reactions
0
Timeline (top)
labeled ×5commented ×1

Error Message

Environment: Cowork desktop (Claude Agent SDK), Windows 11 Date observed: 2026-04-24 Severity: High — silent data loss with no error surfaced to the agent or user. When the Edit tool is called repeatedly on the same large JavaScript file with multi-line old_string / new_string replacements, after roughly 3 successful calls the tool reports "The file has been updated successfully" but the file on disk is truncated mid-content (mid-statement, mid-line, mid-word). No error is raised. The Read tool, called immediately after, returns the pre-truncation cached contents for several seconds, so the agent has no way to detect the corruption until a separate process (bash, node) reads the actual file. return json(400, { error: Only these file types are allowed: ${Object.keys(ALLOWED_EXTENSIONS).join(', ')} });$

  1. Instrument Edit to compare file length before/after. After a successful write, re-read the first and last 256 bytes and confirm the new content contains both the prefix and suffix the agent expected. If not, return a hard error instead of "success".

Root Cause

=== Actual disk state a moment later === $ wc -l upload.js 255 upload.js # was 293 before the Edit calls $ node -c upload.js SyntaxError: Unexpected end of input at wrapSafe (node:internal/modules/cjs/loader:1638:18) $ tail -1 upload.js | cat -A return json(400, { error: Only these file types are allowed: ${Object.keys(ALLOWED_EXTENSIONS).join(', ')} });$

file ends here, mid-function, no closing braces, no final function json() helper

The file was truncated at byte offset ~11 500 in the middle of an if branch. Everything after was gone. Scope • Affected files observed in this session: upload.js, adminConfig.js, getContentUrl.js, serveContent.js, auth.js — all Azure Functions source files between 7 KB and 18 KB in size. • Not path-dependent. Initially suspected the parent path contained a Unicode LTR-mark (U+200E) and that the truncation was a Windows path-encoding issue. Moved files to a clean ASCII-only scratchpad path (outputs/functions-staging/) and re-ran. Same truncation reproduced there. • Workaround: Python open()/write() and bash cat >> / sed applied on the exact same files, same path, same operations — worked correctly on the first try with no truncation. Syntax-check passed. 12 of 12 production files validated. Why this is high-severity

  1. Silent failure. The Edit tool claims success. There is no status: truncated, no warning, no mismatch signal. An agent that finishes a task with 5 successful Edit calls has no reason to re-verify each file byte-by-byte.
  2. Trusted production code path. The user was editing live Azure Functions backing a client portal. Had the agent not run a node -c check afterwards, the broken files would have been committed and deployed.
  3. Read cache desynchronisation. After the truncation, Read returned the pre-truncation content for multiple turns. This actively misleads the agent into believing the file is fine. The agent only discovered the problem because bash/node view the real disk state, not the cached view.
  4. Non-obvious trigger. It isn't the first Edit call that fails, and it isn't tied to payload size. It appears to emerge after repeated calls on the same file, and survives across different folders. Proposed triage
  5. Instrument Edit to compare file length before/after. After a successful write, re-read the first and last 256 bytes and confirm the new content contains both the prefix and suffix the agent expected. If not, return a hard error instead of "success".
  6. Invalidate Read cache on every Edit. The discrepancy between Read output and actual disk content is arguably the more dangerous half of this bug.
  7. Add a telemetry event (edit_tool.apparent_success_with_file_shrink) that fires when the post-edit file is more than N bytes smaller than the sum of expected changes, and surface it in Cowork logs. This will let Anthropic measure real-world incidence.
  8. Document in tool help that large JS file refactors should prefer a scripted approach (Python or bash heredoc) until the underlying bug is fixed. Workaround we landed on For the refactor we were doing (hoisting constants to the top of 5 files, renaming MAX_RETRIES → WRITE_MAX_RETRIES, aligning a 2 MB size limit), switching to a single Python str.replace script applied all five files' changes in one run with zero issues. The same replacements, staged through Edit across multiple turns, truncated all five. Working pattern:

Applied from bash via pyt…

Note: Content was truncated.

Fix Action

Fix / Workaround

=== Actual disk state a moment later === $ wc -l upload.js 255 upload.js # was 293 before the Edit calls $ node -c upload.js SyntaxError: Unexpected end of input at wrapSafe (node:internal/modules/cjs/loader:1638:18) $ tail -1 upload.js | cat -A return json(400, { error: Only these file types are allowed: ${Object.keys(ALLOWED_EXTENSIONS).join(', ')} });$

file ends here, mid-function, no closing braces, no final function json() helper

The file was truncated at byte offset ~11 500 in the middle of an if branch. Everything after was gone. Scope • Affected files observed in this session: upload.js, adminConfig.js, getContentUrl.js, serveContent.js, auth.js — all Azure Functions source files between 7 KB and 18 KB in size. • Not path-dependent. Initially suspected the parent path contained a Unicode LTR-mark (U+200E) and that the truncation was a Windows path-encoding issue. Moved files to a clean ASCII-only scratchpad path (outputs/functions-staging/) and re-ran. Same truncation reproduced there. • Workaround: Python open()/write() and bash cat >> / sed applied on the exact same files, same path, same operations — worked correctly on the first try with no truncation. Syntax-check passed. 12 of 12 production files validated. Why this is high-severity

  1. Silent failure. The Edit tool claims success. There is no status: truncated, no warning, no mismatch signal. An agent that finishes a task with 5 successful Edit calls has no reason to re-verify each file byte-by-byte.
  2. Trusted production code path. The user was editing live Azure Functions backing a client portal. Had the agent not run a node -c check afterwards, the broken files would have been committed and deployed.
  3. Read cache desynchronisation. After the truncation, Read returned the pre-truncation content for multiple turns. This actively misleads the agent into believing the file is fine. The agent only discovered the problem because bash/node view the real disk state, not the cached view.
  4. Non-obvious trigger. It isn't the first Edit call that fails, and it isn't tied to payload size. It appears to emerge after repeated calls on the same file, and survives across different folders. Proposed triage
  5. Instrument Edit to compare file length before/after. After a successful write, re-read the first and last 256 bytes and confirm the new content contains both the prefix and suffix the agent expected. If not, return a hard error instead of "success".
  6. Invalidate Read cache on every Edit. The discrepancy between Read output and actual disk content is arguably the more dangerous half of this bug.
  7. Add a telemetry event (edit_tool.apparent_success_with_file_shrink) that fires when the post-edit file is more than N bytes smaller than the sum of expected changes, and surface it in Cowork logs. This will let Anthropic measure real-world incidence.
  8. Document in tool help that large JS file refactors should prefer a scripted approach (Python or bash heredoc) until the underlying bug is fixed. Workaround we landed on For the refactor we were doing (hoisting constants to the top of 5 files, renaming MAX_RETRIES → WRITE_MAX_RETRIES, aligning a 2 MB size limit), switching to a single Python str.replace script applied all five files' changes in one run with zero issues. The same replacements, staged through Edit across multiple turns, truncated all five. Working pattern:

Applied from bash via pyt…

Note: Content was truncated.

RAW_BUFFERClick to expand / collapse

Bug Description

Bug report — Edit tool silently truncates files after multiple block-style replacements Environment: Cowork desktop (Claude Agent SDK), Windows 11 Date observed: 2026-04-24 Severity: High — silent data loss with no error surfaced to the agent or user. Summary When the Edit tool is called repeatedly on the same large JavaScript file with multi-line old_string / new_string replacements, after roughly 3 successful calls the tool reports "The file has been updated successfully" but the file on disk is truncated mid-content (mid-statement, mid-line, mid-word). No error is raised. The Read tool, called immediately after, returns the pre-truncation cached contents for several seconds, so the agent has no way to detect the corruption until a separate process (bash, node) reads the actual file. Reproduction

  1. Start with a valid JS file ~13 KB / ~290 lines (e.g., an Azure Function handler).
  2. Call Edit tool three times in sequence, each replacing a block of roughly 15–60 lines with a new block of similar size, all with unique old_strings present verbatim in the file.
  3. After the third call, run wc -l and node -c via bash on the same path. Observed: the file is truncated at a position unrelated to any edit (mid-line, often mid-identifier). Syntax check fails with Unexpected end of input or Invalid or unexpected token. Each Edit call still returned success. Minimal evidence from this session === Edit tool said === The file <...>/upload.js has been updated successfully. (file state is current in your context — no need to Read it back)

=== Actual disk state a moment later === $ wc -l upload.js 255 upload.js # was 293 before the Edit calls $ node -c upload.js SyntaxError: Unexpected end of input at wrapSafe (node:internal/modules/cjs/loader:1638:18) $ tail -1 upload.js | cat -A return json(400, { error: Only these file types are allowed: ${Object.keys(ALLOWED_EXTENSIONS).join(', ')} });$

file ends here, mid-function, no closing braces, no final function json() helper

The file was truncated at byte offset ~11 500 in the middle of an if branch. Everything after was gone. Scope • Affected files observed in this session: upload.js, adminConfig.js, getContentUrl.js, serveContent.js, auth.js — all Azure Functions source files between 7 KB and 18 KB in size. • Not path-dependent. Initially suspected the parent path contained a Unicode LTR-mark (U+200E) and that the truncation was a Windows path-encoding issue. Moved files to a clean ASCII-only scratchpad path (outputs/functions-staging/) and re-ran. Same truncation reproduced there. • Workaround: Python open()/write() and bash cat >> / sed applied on the exact same files, same path, same operations — worked correctly on the first try with no truncation. Syntax-check passed. 12 of 12 production files validated. Why this is high-severity

  1. Silent failure. The Edit tool claims success. There is no status: truncated, no warning, no mismatch signal. An agent that finishes a task with 5 successful Edit calls has no reason to re-verify each file byte-by-byte.
  2. Trusted production code path. The user was editing live Azure Functions backing a client portal. Had the agent not run a node -c check afterwards, the broken files would have been committed and deployed.
  3. Read cache desynchronisation. After the truncation, Read returned the pre-truncation content for multiple turns. This actively misleads the agent into believing the file is fine. The agent only discovered the problem because bash/node view the real disk state, not the cached view.
  4. Non-obvious trigger. It isn't the first Edit call that fails, and it isn't tied to payload size. It appears to emerge after repeated calls on the same file, and survives across different folders. Proposed triage
  5. Instrument Edit to compare file length before/after. After a successful write, re-read the first and last 256 bytes and confirm the new content contains both the prefix and suffix the agent expected. If not, return a hard error instead of "success".
  6. Invalidate Read cache on every Edit. The discrepancy between Read output and actual disk content is arguably the more dangerous half of this bug.
  7. Add a telemetry event (edit_tool.apparent_success_with_file_shrink) that fires when the post-edit file is more than N bytes smaller than the sum of expected changes, and surface it in Cowork logs. This will let Anthropic measure real-world incidence.
  8. Document in tool help that large JS file refactors should prefer a scripted approach (Python or bash heredoc) until the underlying bug is fixed. Workaround we landed on For the refactor we were doing (hoisting constants to the top of 5 files, renaming MAX_RETRIES → WRITE_MAX_RETRIES, aligning a 2 MB size limit), switching to a single Python str.replace script applied all five files' changes in one run with zero issues. The same replacements, staged through Edit across multiple turns, truncated all five. Working pattern:

Applied from bash via pyt…

Note: Content was truncated.

extent analysis

TL;DR

The Edit tool's silent truncation of files after multiple block-style replacements can be mitigated by instrumenting the tool to compare file lengths before and after edits and invalidating the Read cache on every Edit.

Guidance

  • Instrument the Edit tool to compare file lengths before and after edits to detect truncation.
  • Invalidate the Read cache on every Edit to ensure the agent has an accurate view of the file contents.
  • Consider using a scripted approach (e.g., Python or bash) for large file refactors until the underlying bug is fixed.
  • Add telemetry events to track instances of apparent success with file shrinkage to measure real-world incidence.

Example

# Example of a scripted approach using Python
with open('file.js', 'r+') as f:
    content = f.read()
    # Apply replacements
    content = content.replace('old_string', 'new_string')
    f.seek(0)
    f.write(content)
    f.truncate()

Notes

The root cause of the truncation issue is unclear, but it appears to be related to repeated calls to the Edit tool on the same file. The proposed triage steps and workaround can help mitigate the issue, but a more thorough investigation is needed to identify the underlying cause.

Recommendation

Apply workaround: use a scripted approach (e.g., Python or bash) for large file refactors until the underlying bug is fixed. This approach has been shown to work correctly and can help prevent silent data loss.

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…

Still need to ship something?

×6

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

Back to top recommendations

TRENDING

claude-code - 💡(How to fix) Fix [Bug] Edit tool silently truncates files after multiple block replacements [1 comments, 2 participants]