anthropics / anthropics/claude-code

[BUG] Cowork: device_commit_files reports success on overwrites but the on-disk content lags exactly one commit behind (silent stale write, fresh mtime)

オープン
#93,482 コメント 2 件 リアクション 0 件 担当者 0 名 GitHub で見る
area:cowork bug data-loss has repro platform:windows
主要言語
Python
スター
145k
フォーク
23.1k
PR マージ指標
PR 指標を取得中

説明

### Preflight Checklist

- [x] I have searched [existing issues](https://github.com/anthropics/claude-code/issues?q=is%3Aissue%20state%3Aopen%20label%3Abug) and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code

### What's Wrong?

## Summary

When a cloud Cowork session writes back to a file that **already exists** on the linked device, `device_commit_files` returns `{"written":[path],"rejected":[]}`, the file's modification time advances to the moment of the call, and **the content on disk is the payload from the previous commit**. Committing the identical payload a second time lands it.

Creating a **new** file is unaffected and correct every time. Only overwrites are affected.

This is a silent data-integrity failure. The session has no signal that anything went wrong, and the file it just "wrote" looks freshly updated to any human or tool inspecting it, because the timestamp is current while the bytes are stale.

## Impact

This is worse than a loud failure for two reasons.

1. **The success response is indistinguishable from a real write.** An agent that follows the obvious contract, commit and move on, will report work as saved that was not saved.
2. **The timestamp lies in the same direction.** A stale file carries the new write's mtime, so ordinary "has this been updated?" checks, sync tools, and human inspection all agree with the false success.

For anyone using a Cowork workspace with recurring update routines, the exposed operations are exactly the common ones: appending to a running log, updating a status line, bumping a version, editing a spec. Every one of those is an overwrite. The drift is invisible until someone reads the file much later.

## Workaround

Commit the same payload twice, then stage the file back and grep the content for the intended change. Byte count is a weak check and the timestamp is no check at all. Where possible, do write-heavy work in Claude Code instead, which writes to disk directly and does not use this path. (Confirmed clean by test on the same machine: new file, two Write-tool overwrites, and one Edit-tool in-place edit, each verified from a separate PowerShell process, all four exact with no lag.)

## Suggested area to look at

The off-by-one shape suggests something in the commit path is buffering or staging the payload and swapping in the previous one for the overwrite case, since the create case is correct. The mtime being updated from the current call while the bytes come from the prior call points at the metadata write and the content write reading from different sources.

### What Should Happen?

After `device_commit_files` returns `written` with no rejections, the file on disk should contain the committed payload. If the write cannot be completed, the call should report the path in `rejected` rather than returning success.

### Error Messages/Logs

```shell

```

### Steps to Reproduce

## Reproduction

Minimal repro, run against a plain local folder (`C:\Users\\Downloads`, **not** OneDrive-backed):

| Step | Action | Committed payload | Commit result | On disk immediately after |
|---|---|---|---|---|
| 1 | `device_commit_files` (new file) | `VERSION-A…` (43 bytes) | `written`, no rejections | **43 bytes, VERSION-A** ✅ |
| 2 | `device_commit_files` (overwrite) | `VERSION-B…` (82 bytes) | `written`, no rejections | **43 bytes, VERSION-A** ❌ (mtime advanced) |
| 3 | `device_commit_files` (same payload again) | `VERSION-B…` (82 bytes) | `written`, no rejections | **82 bytes, VERSION-B** ✅ |
| 4 | `device_commit_files` (overwrite) | `VERSION-C…` (89 bytes) | `written`, no rejections | **82 bytes, VERSION-B** ❌ (mtime advanced) |
| 5 | Wait 45 s, re-read, **no** intervening commit | — | — | **82 bytes, VERSION-B** ❌ |

Payload lengths were chosen to differ, so byte count alone distinguishes the revisions without inspecting content. Content was checked as well via `device_stage_files` and matched the byte count in every case.

## What this rules out

- **Not a read cache.** Step 5 waited 45 seconds with no intervening commit and the stale content persisted. `device_list_dir` and `device_stage_files` agreed with each other at every step.
- **Not OneDrive.** First observed on files under a OneDrive-synced folder, then reproduced identically in `C:\Users\\Downloads`, outside OneDrive entirely.
- **Not KB5124008.** That update broke the Hyper-V Plan9 shares used by `device_bash` on this machine (see #92984). The local sandbox shell was completely non-functional throughout this testing while the file bridge kept working, so the two are on different code paths.
- **Not `force`.** Behavior is identical with and without `force: true`, and with and without `expectedMtimeMs`.

## Observed elsewhere in the same session

Reproduced five separate times across four different files before it was isolated:

- two markdown files under a OneDrive-synced connected folder (~8 KB and ~65 KB), twice each
- a `.ps1` script file in the same folder
- the `Downloads` test file above

In every case the pattern was the same: first commit reports success and leaves the prior revision, second identical commit lands the new content.

### Claude Model

Opus

### Is this a regression?

Yes, this worked in a previous version

### Last Working Version

_No response_

### Claude Code Version

Claude Desktop | 1.49585.0 |

### Platform

Anthropic API

### Operating System

Windows

### Terminal/Shell

Other

### Additional Information

## Environment

| | |
|---|---|
| Claude Desktop | 1.49585.0 |
| Platform | win32 x64 |
| Electron / Node | 44.2.0 / 24.20.0 |
| OS | Windows 11 25H2, OS Build 26200.9445 |
| Session type | Cowork **cloud** session linked to a desktop device |
| Model | claude-opus-5 |

## Related Issue

This may be related to: https://github.com/anthropics/claude-code/issues/83354

コントリビューションガイド

このリポジトリのコントリビューションガイドは索引されていません

調査の方向性

Start at the device_commit_files entry point and compare its overwrite path with device_stage_files and device_list_dir using the Windows reproduction steps. Verify that each successful overwrite leaves the committed payload on disk immediately, and that failed writes are reported in rejected rather than written.

索引モデルが issue の本文から書いたものです。

評価

技術スタック
electron, node.js
領域
api, desktop
issue の種類
バグ
難易度
4/5
見積もり時間
3〜5日
活発さ
活発
明瞭さ
おおむね明確
初心者へのやさしさ
48/100

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。