Skip to content

fix: clean up orphaned worktrees on bootstrap failure#14649

Open
alexhraber wants to merge 3 commits intoanomalyco:devfrom
alexhraber:dev
Open

fix: clean up orphaned worktrees on bootstrap failure#14649
alexhraber wants to merge 3 commits intoanomalyco:devfrom
alexhraber:dev

Conversation

@alexhraber
Copy link
Copy Markdown

Issue for this PR

Closes #14648

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

Worktree.create in packages/opencode/src/worktree/index.ts fires off bootstrap work (git reset + Instance.provide) inside a setTimeout(..., 0) and returns immediately. When that deferred bootstrap fails — either git reset --hard exits non-zero or Instance.provide() throws — the function just logs, emits a worktree.failed event, and returns. Nothing cleans up the artifacts that were already created synchronously before the setTimeout:

  1. The worktree directory at ~/.local/share/opencode/worktree/<project-id>/<random-name>/
  2. The git worktree entry in .git/worktrees/
  3. The git branch opencode/<random-name>
  4. The sandbox record in the project database

Each retry generates a new random name (brave-cabin, calm-cactus, etc.), so repeated failures accumulate orphaned full-repo clones with no upper bound and no automatic cleanup.
This is what causes the disk fillups.

The fix adds a cleanupFailedWorktree async helper that tears down all four artifacts. It's called from every failure path: git reset failure, Instance.provide failure, and the outer
.catch() on the start promise. The cleanup is intentionally best-effort (each step catches its own errors) so a partial cleanup failure doesn't mask the original bootstrap error.

I captured Instance.worktree into worktreeCwd before entering the setTimeout to ensure the git commands in cleanup have a stable cwd reference.

How did you verify your code works?

  • Read through the existing Worktree.remove logic to match the same cleanup steps (directory rm with retries, git worktree remove --force, git worktree prune, git branch -D, Project.removeSandbox)
  • Verified the existing test in packages/opencode/test/project/worktree-remove.test.ts exercises the remove path and confirms directory, git entry, and branch are all gone after removal
  • Traced all three failure paths in the deferred bootstrap to confirm cleanup is reached in every case

Screenshots / recordings

N/A — no UI changes.

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

When worktree bootstrap fails (either at git reset or Instance.provide),
the worktree directory, git worktree entry, git branch, and database
sandbox record were all left behind permanently. Each failed attempt
creates a new randomly-named worktree, so repeated failures cause
unbounded disk consumption in ~/.local/share/opencode/worktree/.

Add a cleanupFailedWorktree helper that runs on every failure path in
the deferred bootstrap, removing:
- the worktree directory (with retries)
- the git worktree entry (+ prune)
- the git branch
- the project sandbox database record
fix: clean up orphaned worktrees on bootstrap failure
@alexhraber
Copy link
Copy Markdown
Author

This typecheck failure is not caused by the worktree change. It's a pre-existing issue in the upstream repo. Here's why:

  1. The enterprise package depends on @opencode-ai/ui, which imports AssistantMessage, FileDiff, Message, Part from @opencode-ai/sdk/v2/client
  2. The SDK's package.json maps "./v2/client" types to ./dist/v2/client.d.ts, but the dist/ directory doesn't exist
  3. The turbo typecheck task has no dependsOn, so it runs without building the SDK first

This cannot be fixed by changing packages/opencode/src/worktree/index.ts - the worktree file has nothing to do with TypeScript type exports from the SDK package. The fix needs to happen in one of:

  • turbo.json - add "dependsOn": ["^build"] to the typecheck task
  • packages/sdk/js/package.json - fix the types condition to point to source
  • packages/ui/src/components/session-turn.tsx - fix the imports

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Worktree bootstrap failures leak orphaned directories causing disk fillup

1 participant