Why 614 Windows junctions defeated a cleanup routine — and why volume snapshots survive it

In late September 2026, a developer asked Claude Code to rebuild and clean up a project. The cleanup went wrong in the worst possible way: the agent followed 614 Windows directory junctions and deleted 48,218 live files in 103 seconds — corrupting the git object database along the way, so even git could not save the work. The agent then apologized: “I broke something.” TechRadar reported the incident, citing the developer’s (since-deleted) Reddit post.

This is worth dissecting, because the failure mode is not exotic. It is a three-way interaction between NTFS junctions, recursive-deletion semantics, and the way AI agents reason about cleanup. And it explains why the only defense that reliably survives this class of accident is a volume-level snapshot taken before the agent acts.

What a junction is (and why programs trip on it)

A junction (mklink /J) is an NTFS reparse point that redirects a directory path to another location on the same volume. It looks like a directory in almost every listing API, but it is a link, not a copy.

The critical detail is in the file attributes: junctions (and symbolic links) carry the FILE_ATTRIBUTE_REPARSE_POINT flag. Code that deletes a directory tree recursively — “enumerate children, recurse, delete, walk up” — will happily follow that reparse point into the target tree unless it explicitly checks the attribute. On Unix, rm -r has special semantics for symlinks (delete the link, not the target). On Windows, homemade recursion has no such convention, and “delete the junction” vs. “delete through the junction” is a single attribute check away from each other.

Why a cleanup routine follows junctions into live data

A typical “clean up the build” prompt produces a recursive delete of an output directory. If that directory — or anything the traversal passes through — contains junctions pointing into the live project tree, and developers create such junctions constantly for node_modules dedup, test fixtures, redirected output, or workspace layouts — then a delete routine that doesn’t treat reparse points as leaves will delete the targets.

The agent isn’t malicious here; it’s doing what a plausible-looking implementation does. The junctions made “delete this directory” mean “delete those files too.” 614 junctions, 103 seconds, 48,218 files.

Why “git will save you” didn’t

Two reasons, both visible in this incident:

  • The git object database was corrupted too. It sat in the blast radius. Version control is a snapshot of tracked source, stored inside the tree being deleted — the same disaster takes out both copies.
  • Junction targets are usually outside the repo. Junctions commonly redirect data away from a repo (shared caches, datasets, user directories). Git never tracked those files in the first place.

The same applies to the other popular “git will protect me” assumptions: git clean -fd and git reset --hard are themselves destructive commands agents run — there is a multi-year Unity project deleted exactly this way in Claude Code’s issue tracker.

Why volume-level snapshots survive this

A Volume Shadow Copy Service (VSS) snapshot is a point-in-time view of the volume, implemented at the storage layer. When the shadow copy is created, the volume’s used blocks are frozen (copy-on-write). Deleting files — even through 614 junctions — only affects the live filesystem’s metadata and blocks. The shadow copy’s blocks are not writable by normal file operations; an agent deleting files cannot reach into the shadow storage.

Recovery is then a copy operation: mount the snapshot, copy the lost files back. In unlose’s test suite, restores are verified byte-for-byte (SHA256) — the “48,218 files” scenario is recoverable in full if a snapshot exists from before the agent started.

What unlose does (briefly)

unlose is a free, open-source (Apache-2.0) Windows service that takes automatic VSS snapshots when AI agents start working — it detects 26+ agents, injects snapshot directives into their memory files (so agents themselves can request a snapshot before risky operations), and gives you a timeline UI to restore anything, file-level or whole-volume. It pairs naturally with command interceptors like DCG: interceptors block what they can; the snapshot catches what they can’t.

Takeaways

  1. Audit recursive-deletion paths for reparse points. If your scripts (or your agents’ scripts) enumerate directories, check FILE_ATTRIBUTE_REPARSE_POINT before recursing.
  2. Junctions + AI agents deserve the same respect as symlinks got on Unix 40 years ago. The semantics gap is real and has now eaten a production project.
  3. Keep the last line of defense outside the blast radius. Git lives inside the tree; cloud sync can propagate deletions. A volume snapshot taken before the agent acts is the only copy the disaster cannot touch.

unlose is a free, open-source (Apache-2.0) Windows snapshot tool: it snapshots your disks before your AI agent acts, and you drag a timeline to get files back.

Download unlose Read the docs