gitbutlerapp/gitbutler · error

`but setup` cannot run from a linked worktree; run it from…

Error message

`but setup` cannot run from a linked worktree; run it from the main worktree{}

What it means

`but setup` (project initialization in `repo()`) discovers the repository with `gix::discover` and refuses to proceed when the discovered git dir differs from the common dir, i.e. the path is a linked worktree (`git worktree add`). GitButler project setup must run from the main worktree; the error appends the main worktree path when it can be resolved.

Solutions

  1. cd to the main worktree (path shown in the error message) and run `but setup` there
  2. Find the main worktree with `git worktree list` (the entry without a `worktree` annotation is main)
  3. Remove the linked worktree if unneeded (`git worktree remove <path>`) and set up from main

Example fix

// before
cd ~/repo-feature-x   # linked worktree
but setup

// after
git worktree list
cd ~/repo             # main worktree
but setup
Defensive patterns

Strategy: validation

Validate before calling

# only run setup from the main worktree
git_dir=$(git rev-parse --git-common-dir)
work_dir=$(git rev-parse --git-dir)
[ "$git_dir" = "$work_dir" ] || { echo "linked worktree; run from main"; exit 1; }

Try / catch

match setup_result {
    Err(e) if e.to_string().starts_with("`but setup` cannot run from a linked worktree") => {
        // parse " at <path>" suffix and switch to main worktree
        let main = parse_main_path(&e.to_string());
        std::env::set_current_dir(main)?;
        return setup_again();
    }
    other => other,
}

Prevention

When it happens

Trigger: Running `but setup` while the current directory is a linked worktree created via `git worktree add`, pointing `-C` at a linked-worktree path, or scripting setup inside a per-worktree CI checkout.

Common situations: Developers using git worktrees for parallel branches who run setup from the wrong checkout; monorepo tooling that materializes linked worktrees; automation that picks the first directory found without checking it is the main worktree.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of gitbutlerapp/gitbutler@58e5313667 (2026-09-18). Data as JSON: /api/errors/26b98f8a8787674e. Report an issue: GitHub.

Appendix: source

Thrown at crates/but/src/command/legacy/setup.rs:192

                anyhow::bail!(
                    "No git repository found - run `but setup --init` to initialize a new repository."
                );
            }
        }
    }
}

// setup a gitbutler project for the repository at `repo_path`
pub(crate) fn repo(
    ctx: &mut Context,
    repo_path: &Path,
    out: &mut OutputChannel,
    perm: &mut RepoExclusive,
) -> anyhow::Result<()> {
    let discovered = gix::discover(repo_path)?;
    if discovered.git_dir() != discovered.common_dir() {
        let main_worktree = discovered.main_repo()?;
        anyhow::bail!(
            "`but setup` cannot run from a linked worktree; run it from the main worktree{}",
            main_worktree
                .workdir()
                .map(|dir| format!(" at {}", dir.display()))
                .unwrap_or_default()
        );
    }
    let t = theme::get();
    let mut target_info: Option<TargetInfo> = None;

    // what branch is head() pointing to?
    let pre_head_name = {
        let repo = ctx.repo.get()?;
        let pre_head = repo.head()?;
        pre_head
            .referent_name()
            .map(|n| n.shorten().to_string())
            .unwrap_or_default()

View on GitHub (pinned to 58e5313667)