fix: clean up orphaned worktrees on bootstrap failure#1
Merged
alexhraber merged 1 commit intodevfrom Feb 22, 2026
Merged
Conversation
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
cleanupFailedWorktreehelper that tears down all worktree artifacts when the deferred bootstrap fails at any stagegit reset --hardfailure,Instance.provide()failure, and unexpected exceptions in the outerstart()promiseProblem
The
Worktree.createfunction has a fire-and-forget bootstrap viasetTimeout(() => {...}, 0)at line 357. Aftergit worktree addsucceeds andProject.addSandbox()registers the worktree, the function returnsinfoimmediately. The actual population (git reset --hard) and bootstrap (Instance.provide()) happen asynchronously.When either of these steps fails:
~/.local/share/opencode/worktree/<project-id>/<name>/.git/worktrees/opencode/<name>remainsNothing ever cleans these up. Each retry generates a unique random name (
brave-cabin,calm-cactus, etc.), so repeated failures create unbounded orphaned worktrees. For large repos, each can be hundreds of MB.Changes
worktree/index.ts:359-376cleanupFailedWorktreeasync helper that removes: directory (with retries), git worktree entry, prunes stale git worktree metadata, deletes the git branch, and removes the sandbox database recordworktree/index.ts:393git reset --hardfailure path now callscleanupFailedWorktree()before returningworktree/index.ts:417-419Instance.provide()failure path now callscleanupFailedWorktree()before returningworktree/index.ts:436-438start().catch()now callscleanupFailedWorktree()for any unexpected errorworktree/index.ts:356Instance.worktreeasworktreeCwdbefore enteringsetTimeoutto ensure stable reference for cleanup git commandsImpact
Before this fix, every failed worktree creation attempt leaked a full repository clone on disk with no way to reclaim the space short of manually finding and deleting orphaned directories. This was the root cause of
/tmpand data directory disk fillups reported by users experiencing repeated bootstrap failures (e.g. network issues, disk pressure, permission errors).Test plan
git reset --hardfails (e.g., corrupt repo state) and verify the worktree directory, git entry, branch, and sandbox record are all cleaned upInstance.provide()throws and verify full cleanupWorktree.remove()still works correctly for explicitly removed worktreesbun test packages/opencode/test/project/worktree-remove.test.ts