gitbutlerapp/gitbutler · error
The repository at {} is a non-main worktree. GitButler requi
Error message
The repository at {} is a non-main worktree. GitButler requires the main worktree. What it means
Raised while registering a repository: the path is a git worktree, but a linked (non-main) one — `AddProjectOutcome::NonMainWorktree`. These are created with `git worktree add` and share the object database with the main worktree; GitButler only supports operating on the main worktree.
Source
Thrown at crates/but/src/command/legacy/setup.rs:246
" {}",
t.success.paint("✓ Repository already in project registry")
)?;
}
Ok(ProjectStatus::AlreadyExists)
}
gitbutler_project::AddProjectOutcome::PathNotFound => Err(anyhow::anyhow!(
"The path {} does not exist",
repo_path.display()
)),
gitbutler_project::AddProjectOutcome::NotADirectory => Err(anyhow::anyhow!(
"The path {} is not a directory",
repo_path.display()
)),
gitbutler_project::AddProjectOutcome::BareRepository => Err(anyhow::anyhow!(
"The repository at {} is bare. GitButler requires a non-bare repository.",
repo_path.display()
)),
gitbutler_project::AddProjectOutcome::NonMainWorktree => Err(anyhow::anyhow!(
"The repository at {} is a non-main worktree. GitButler requires the main worktree.",
repo_path.display()
)),
gitbutler_project::AddProjectOutcome::NoWorkdir => Err(anyhow::anyhow!(
"The repository at {} has no working directory. GitButler requires a working directory.",
repo_path.display()
)),
gitbutler_project::AddProjectOutcome::NoDotGitDirectory => Err(anyhow::anyhow!(
"The repository at {} has no .git directory. GitButler requires a .git directory.",
repo_path.display()
)),
gitbutler_project::AddProjectOutcome::ReftableRefFormatUnsupported => Err(anyhow::anyhow!(
"The repository at {} uses the currently unsupported reftable reference format.",
repo_path.display()
)),
gitbutler_project::AddProjectOutcome::NotAGitRepository(_) => Err(anyhow::anyhow!(
"The path {} is not a git repository.",
repo_path.display()View on GitHub (pinned to caf1f223d3)
Solutions
- Run setup in the main worktree of the clone (where the real `.git` directory lives)
- Find the main worktree from the linked one: `git -C /the/path rev-parse --git-common-dir` strips the trailing path — or check `git worktree list`
- If you need isolation, clone the repository again instead of using a linked worktree
Example fix
# before: linked worktree created by 'git worktree add' but setup ~/hotfix-worktree # after: main worktree of the same clone git -C ~/hotfix-worktree worktree list # locate the main checkout but setup ~/repos/project # the main worktree
Defensive patterns
Strategy: validation
Validate before calling
let output = std::process::Command::new("git")
.args(["-C", repo_path.to_str().unwrap(), "rev-parse", "--git-path", ".."])
.output()?;
// simpler: compare git-dir and git-common-dir
let git_dir = std::process::Command::new("git").args(["-C", path, "rev-parse", "--git-dir"]).output()?;
let common_dir = std::process::Command::new("git").args(["-C", path, "rev-parse", "--git-common-dir"]).output()?;
if git_dir.stdout != common_dir.stdout {
anyhow::bail!("linked worktree; register the main worktree instead");
} Type guard
fn is_non_main_worktree(out: &gitbutler_project::AddProjectOutcome) -> bool {
matches!(out, gitbutler_project::AddProjectOutcome::NonMainWorktree)
} Try / catch
match add_project(&repo_path) {
Ok(out) if is_non_main_worktree(&out) => { /* locate main worktree via 'git worktree list' */ }
Ok(out) => { /* other outcomes */ }
Err(err) if err.to_string().contains("non-main worktree") => { /* worktree guidance */ }
Err(err) => return Err(err),
} Prevention
- Detect linked worktrees early: `.git` being a file (not a directory) is the tell
- Use `git worktree list` to find the main checkout before registering projects
- Prefer a separate clone over `git worktree add` when a tool will manage the repo
When it happens
Trigger: Running setup inside a directory created by `git worktree add ../hotfix` (its `.git` is a file pointing back at the main repo's worktrees area), rather than in the original clone.
Common situations: Developers using linked worktrees for parallel branches; CI agents reusing a worktree checkout; opening a worktree directory from a recent-files list.
Related errors
- The repository at {} has no working directory. GitButler req
- The repository at {} is bare. GitButler requires a non-bare
- The repository at {} has no .git directory. GitButler requir
- The repository at {} uses the currently unsupported reftable
- The path {} is not a git repository.
AI-assisted analysis of gitbutlerapp/gitbutler@caf1f223d3 (2026-08-20).
Data as JSON: /api/errors/267adecb48e258d7.
Report an issue: GitHub.