Skip to content

[Bug]: Storage cleanup keeps every worktree in a project when origin/HEAD is unset ("Default branch is unavailable") #17807

Description

@tris203

Before submitting

  • I searched existing issues and did not find a duplicate.
  • I included enough detail to reproduce or investigate the problem.

Area

apps/server

Steps to reproduce

A repository whose remote was added with git remote add has no refs/remotes/origin/HEAD. Only git clone (or git remote set-head) creates it.

git init -q --bare -b main remote.git
git init -q -b main project && cd project
git commit -q --allow-empty -m init
git remote add origin ../remote.git
git push -q -u origin main

git symbolic-ref refs/remotes/origin/HEAD
# fatal: ref refs/remotes/origin/HEAD is not a symbolic ref   (exit 128)
git show-ref --verify refs/remotes/origin/main
# <sha> refs/remotes/origin/main                              (the branch is there)
  1. Add project as a T3 project.
  2. In Settings → Storage, turn on Delete unchanged worktrees and/or Delete merged worktrees.
  3. Start a thread in a new worktree, make no commits, and let it go idle.
  4. Run the cleanup.

Expected behavior

The worktree is removed with "No commits beyond the default branch." origin/main exists and the worktree's HEAD is an ancestor of it.

Actual behavior

Every worktree in the project is kept with "Default branch is unavailable." The unchanged and merged rules never run for that project, so only the inactivity rule can remove anything.

cleanWorktrees stops as soon as resolveDefaultBranchName returns null, and that function returns null whenever git symbolic-ref refs/remotes/<remote>/HEAD exits non-zero.

Other callers already handle the missing ref by falling back to main/master: resolveBaseBranchForNoUpstream, statusDetails, and branchPullRequest. Cleanup is the one that gives up.

The report line also gives the user nothing to act on: it names neither the remote nor the missing ref nor a remedy.

Evidence: the git commands above were run as written (git 2.43.0). The kept reason was observed on a real project in this state, where the cleanup kept 40 worktrees (about 32 GB); 43 of that project's worktrees have no commits beyond origin/main. I did not run a server against the throwaway repository above.

This is separate from #14843 and #17314. Those are about which remote is the base in a fork checkout, and #14843's reproduction has both remote HEAD refs set. This one happens with a single remote.

Suggested direction

When the remote HEAD is missing, probe main then master on the primary remote with the existing remoteBranchExists, as the callers above do. The fetch that follows already confirms the branch exists on the remote. Resolving the remote and default branch once per repository per sweep (today it is once per worktree) would keep the cost below what it is now.

If nothing resolves, a reason such as "Could not tell origin's default branch. Run git remote set-head origin --auto in the project." would be actionable.

Impact

Major degradation or frequent failure

Version or commit

main at f7664fd; observed on server nightly 0.0.46-nightly.20261010.2922

Environment

Linux, git 2.43.0

Workaround

Run git remote set-head origin --auto in the project checkout. Git 2.48 and later may create the ref on a plain git fetch, so older Git versions are the ones most exposed.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions