Fixing Roo Code Silently Overwriting External File Changes Made Mid-Task
A formatter runs on save, a teammate pushes a change pulled into the same branch, or a developer tweaks a line directly in the editor while Roo Code is mid-task on the same file — and the next time the agent writes to that file, the external change is simply gone, with no warning that anything was overwritten. The agent isn't misbehaving; it's writing based on content it read before the external change happened, with nothing in between checking whether that content is still accurate.
The Problem
During a Roo Code task that spans several steps on the same file — reading it, reasoning about a change, then writing the result — something else modifies that file in between: a save-time formatter or linter auto-fix, a git pull or merge bringing in a teammate's change, or the developer directly editing a line in the editor while the task is still running. The next write Roo Code makes to that file succeeds without any visible error, but the external change made in between is simply gone, replaced by a write based on the file's content from before that change happened.
Why It Happens
The agent's working copy of a file's content is a snapshot taken at the moment it was read, not a live view
When Roo Code reads a file as part of a task, what it actually has afterward is the content of that file at that specific instant — a snapshot. Every subsequent reasoning step and edit operates against that snapshot in memory, not against whatever the file on disk happens to contain right now. If the file changes on disk after that snapshot was taken, nothing about the snapshot itself updates to reflect it; the agent genuinely has no way to know the file changed unless something explicitly re-checks.
A write operation based on a stale snapshot overwrites whatever is currently on disk, regardless of what changed there
When the agent finally writes its edit back to the file — whether as a full file write or an applied diff computed against the snapshot — that write operation replaces the file's current on-disk content with the new version, which was built from the old snapshot. Any change that happened on disk in the meantime, external to the snapshot the edit was based on, isn't merged or preserved in any way; it's simply not part of what the write operation is producing at all.
Automated tooling that runs on save specifically creates a narrow but real window for this, because it happens outside the agent's own action sequence entirely
A formatter or linter configured to run automatically whenever a file is saved operates independently of the agent's task flow — it can fire the moment the agent's own write touches the file, or from an entirely separate save triggered by the developer, with no coordination between the two processes at all. If the agent's next read of that file doesn't happen to occur after the formatter's own pass, the formatter's changes exist on disk for a window the agent's snapshot-based model has no visibility into, and a subsequent agent write during that window discards them.
The Fix
1. Avoid running other tools against the same files a task is actively working on, where that's practical
While a Roo Code task is mid-flight on a specific set of files, hold off on
unrelated git pulls, manual edits, or triggering a separate build/format pass
against those same files until the task completes.
Since the core issue is a race between the agent's snapshot and an external change, the most direct fix is simply narrowing the window where that race can happen at all — avoiding concurrent external edits to the exact files a task is working on removes the opportunity for the conflict rather than needing to resolve it after the fact.
2. Disable save-time auto-formatting specifically for files the agent is actively editing, or apply it in a separate, deliberate pass afterward
// .vscode/settings.json — scope auto-format-on-save away from files
// under active agent modification, or disable it project-wide during
// an agent-heavy session and run the formatter manually afterward:
{
"editor.formatOnSave": false
}
Running the formatter as a deliberate, separate step after the agent's task completes — rather than letting it fire automatically and asynchronously during the task — removes the specific, narrow race condition that save-time tooling creates, since there's no longer a formatter pass happening at an unpredictable moment relative to the agent's own reads and writes.
3. Review the diff of what the agent actually changed before trusting it, specifically on files known to have other activity
# After the task completes, diff against the pre-task state rather than
# just trusting the task's own summary of what it changed:
git diff HEAD -- path/to/file.js
Reviewing the actual resulting diff against the file's state from before the task started, rather than relying solely on the agent's own description of what it did, is what catches an overwritten external change concretely — the agent's summary reflects what it intended to do based on its snapshot, not necessarily what ended up on disk relative to everything else that touched the file.
4. If an external change is suspected to have been lost, check version control history rather than assuming it's unrecoverable
# A formatter's auto-fix or a manual edit that got overwritten is often
# still recoverable if it was ever staged or committed, even briefly:
git log -p --follow -- path/to/file.js
git reflog
An overwritten change is lost only from the working directory's current state — if it was staged, committed, or exists in the reflog at any point, it's recoverable through normal git history inspection, which is worth checking before assuming the change has to be redone manually from scratch.
Why This Works
Each step either narrows the specific window where the snapshot-versus-disk race can occur, or catches its consequence after the fact. Avoiding concurrent external edits to the same files removes the opportunity for the race entirely, which is the most reliable fix when it's practical. Disabling save-time auto-formatting during active agent work eliminates a specific, common, and otherwise invisible source of exactly this race. Reviewing the actual diff rather than trusting a task summary catches a lost change concretely instead of assuming everything landed correctly. And checking version control history recovers a change that might otherwise be assumed gone for good, since git typically retains more history than a quick look at the working directory suggests.
Conclusion
A change made outside Roo Code that silently disappears after the agent's next write isn't the agent behaving incorrectly — it's a snapshot of a file's content, read at one moment, being written back without any mechanism checking whether the file changed on disk in between. Avoid running other tools against the exact files a task is actively working on, disable save-time auto-formatting during agent-heavy work or apply it as a deliberate pass afterward, review the actual diff against the pre-task state rather than trusting a task summary, and check version control history before assuming a lost change is unrecoverable.
