Skip to content

Snapshot feature consumes 533GB+ of disk due to orphaned git temp files and unbounded growth #15977

Description

@Bewinxed

Note

Automated bug report — This issue was filed by an AI coding agent (Claude Code) on behalf of @Bewinxed after diagnosing a disk space emergency. All data below was collected programmatically from the affected system.

Summary

The snapshot feature in ~/.local/share/opencode/snapshot/ consumed 533GB of disk space, filling a 1.1TB drive to 100% and causing system-wide issues. The root cause is a combination of:

  1. Abandoned git gc temporary pack files (269GB in one snapshot alone)
  2. Unbounded loose object accumulation in the global snapshot (264GB across 258 object directories)
  3. No disk usage limits, monitoring, or cleanup beyond a weekly git gc --prune=7.days

Environment

  • OpenCode version: 1.2.16
  • OS: WSL2 (Ubuntu), kernel 6.6.87.2-microsoft-standard-WSL2
  • Git: 2.43.0
  • Disk: 1.1TB ext4 (was at 100%, now at 49% after manual cleanup)

Disk Usage Breakdown (Before Cleanup)

~/.local/share/opencode/snapshot/                     533G total
├── 0e0047b09bd609bdead33d952df5f2cf35d8207b/         270G  (project snapshot)
│   └── objects/pack/
│       ├── pack-331804b1...pack                       749M  (actual data, corrupted)
│       ├── tmp_pack_tK4eX9                            125G  ← abandoned gc temp file
│       ├── tmp_pack_mteked                             72G  ← abandoned gc temp file
│       └── tmp_pack_rAcec1                             72G  ← abandoned gc temp file
│   └── objects/79/                                    813M  (loose objects)
├── global/                                           264G  (global snapshot)
│   └── objects/pack/
│       └── tmp_pack_pjs4ru                             58G  ← abandoned gc temp file
│   └── objects/{56,57,64,82,94,a2,bb,cb,f0,...}/    ~1.3G each × 258 dirs
│                                                    (~206G of loose objects)
└── (5 other snapshots)                               ~92M  (normal size)

Root Cause Analysis

I traced this to the snapshot implementation in src/snapshot/index.ts. Several design issues contribute:

1. Failed git gc leaves massive temp files with no cleanup

The hourly git gc --prune=7.days scheduler can fail (e.g., out of disk space, process killed, OOM) and leave tmp_pack_* files in objects/pack/. These are never cleaned up. On my system, three abandoned temp files totaled 269GB in a single snapshot repo.

Suggested fix: Before running git gc, clean up any existing tmp_pack_* files in objects/pack/. Or add a pre-gc check like:

find "${gitdir}/objects/pack" -name 'tmp_pack_*' -mmin +60 -delete

2. global snapshot accumulates unbounded loose objects

The global snapshot had 258 object hash directories averaging 1.3GB each (~206GB of loose objects). Since write-tree creates tree objects without commits, and the index references them, git gc --prune=7.days may not actually prune them (they're technically reachable from the index).

Suggested fix: Periodically reset the snapshot index, or use git prune with more aggressive settings. Consider git gc --aggressive or manual git repack -a -d with pack size limits.

3. No disk usage limits or monitoring

There is no cap on snapshot storage. No check like "if snapshot dir exceeds N GB, purge old data." The only cleanup mechanism is the hourly git gc, which as shown above, can itself fail and worsen the problem.

Suggested fix: Add a configurable max size (e.g., snapshot.maxSize in config). Before each Snapshot.track(), check total size and aggressively prune or disable snapshots if the limit is exceeded.

4. No .gitignore-equivalent for the global snapshot

While git add . respects the project's .gitignore, the global snapshot doesn't have clear exclusion rules for large directories like ~/.cache/huggingface (92GB), ~/.cache/uv (31GB), etc. If the global snapshot's worktree covers the home directory, these all get tracked.

Steps to Reproduce

  1. Use opencode on multiple projects for an extended period (days/weeks)
  2. Have projects with large working trees
  3. Let the hourly git gc scheduler run (and occasionally fail, e.g., due to disk pressure)
  4. Check du -sh ~/.local/share/opencode/snapshot/

Workaround

# Nuclear option — delete all snapshots (loses undo history)
rm -rf ~/.local/share/opencode/snapshot/*

# Or disable snapshots entirely in .opencode.json
# { "snapshot": false }

Suggested Improvements

  1. Clean up tmp_pack_* files before/after git gc runs
  2. Add a total size cap with automatic pruning when exceeded
  3. Add a startup health check that warns if snapshot storage exceeds a threshold
  4. Use git commit-tree instead of orphaned write-tree so gc can properly manage object lifetime via commit reachability
  5. Log snapshot storage size periodically so users can monitor growth
  6. Consider using git gc --auto instead of unconditional git gc to let git decide when gc is needed

Metadata

Metadata

Assignees

Labels

coreAnything pertaining to core functionality of the application (opencode server stuff)needs:complianceThis means the issue will auto-close after 2 hours.perfIndicates a performance issue or need for optimizationwindows

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions