gitbutlerapp/gitbutler · error
non-main worktrees are not supported
Error message
non-main worktrees are not supported
What it means
AddProjectOutcome::NonMainWorktree mapped through try_project: the path is a git linked worktree (created with `git worktree add`), not the repository's main worktree. GitButler manages the main worktree (it writes refs and workspace state under the repo's primary .git dir) and rejects secondary worktrees.
Source
Thrown at crates/gitbutler-project/src/project.rs:327
AddProjectOutcome::Added(p) => p,
_ => panic!("called `AddProjectOutcome::unwrap_project()` on a non-project outcome"),
}
}
/// Try to get the `Project`, returning an error if it was not added.
pub fn try_project(self) -> anyhow::Result<Project> {
match self {
AddProjectOutcome::Added(p) => Ok(p),
AddProjectOutcome::AlreadyExists(_) => Err(anyhow::anyhow!("project already exists")),
AddProjectOutcome::PathNotFound => Err(anyhow::anyhow!("project path not found")),
AddProjectOutcome::NotADirectory => {
Err(anyhow::anyhow!("project path is not a directory"))
}
AddProjectOutcome::BareRepository => {
Err(anyhow::anyhow!("bare repositories are not supported"))
}
AddProjectOutcome::NonMainWorktree => {
Err(anyhow::anyhow!("non-main worktrees are not supported"))
}
AddProjectOutcome::NoWorkdir => Err(anyhow::anyhow!("no workdir found for repository")),
AddProjectOutcome::NoDotGitDirectory => {
Err(anyhow::anyhow!("no .git directory found in repository"))
}
AddProjectOutcome::ReftableRefFormatUnsupported => Err(anyhow::anyhow!(
"unsupported repository reference format: reftable"
)),
AddProjectOutcome::NotAGitRepository(msg) => {
Err(anyhow::anyhow!("not a git repository: {msg}"))
}
}
}
}
View on GitHub (pinned to caf1f223d3)
Solutions
- Add the main worktree instead — resolve the main path with `git worktree list` and pass that directory
- If you need an isolated checkout, clone the repository rather than using a linked worktree
- Pre-detect: a `.git` regular file (not directory) containing `gitdir:` indicates a linked worktree
Example fix
// before
let project = add_project(&path, ...).try_project()?; // linked worktree -> rejected
// after: resolve to the main worktree first
fn main_worktree(path: &Path) -> Option<PathBuf> {
let out = std::process::Command::new("git")
.args(["-C", path.to_str()?, "worktree", "list", "--porcelain"])
.output().ok()?;
let line = String::from_utf8(out.stdout).ok()?.lines().next()?;
line.strip_prefix("worktree ").map(PathBuf::from)
}
let path = main_worktree(&path).unwrap_or(path);
let project = add_project(&path, ...).try_project()?; Defensive patterns
Strategy: validation
Validate before calling
// a linked worktree has a .git *file* pointing at the main repo's worktrees dir
let dot = path.join(".git");
let is_linked_worktree = dot.is_file()
&& std::fs::read_to_string(&dot).map(|c| c.starts_with("gitdir:")).unwrap_or(false);
if is_linked_worktree {
// resolve the main worktree: git -C <path> worktree list --porcelain | head -1
anyhow::bail!("linked worktree — add the main worktree instead");
} Type guard
fn is_main_worktree(path: &Path) -> bool {
let dot = path.join(".git");
dot.is_dir() // main worktrees have a .git directory; linked ones have a gitdir: file
} Try / catch
match add_project(&path, ...) {
AddProjectOutcome::NonMainWorktree => offer_to_add_main_worktree(&path), // resolve via `git worktree list`
outcome => outcome.try_project(),
} Prevention
- Detect linked worktrees by the .git gitdir-pointer file and steer users to the main worktree
- Remember the main worktree per repository so re-adds target it automatically
- Prefer fresh clones over linked worktrees when isolated checkouts are needed
When it happens
Trigger: add_project on a directory whose .git is a file pointing at <main>/.git/worktrees/<name>; multiple `git worktree add` checkouts of the same repo; adding the same repository twice through two of its worktrees.
Common situations: Developers using linked worktrees for parallel branches trying to onboard each one; automation that picks an existing checkout which happens to be a linked worktree.
Related errors
- no workdir found for repository
- HTTP Error ${response.statusText}: ${text}
- bare repositories are not supported
- no .git directory found in repository
- not a git repository: {msg}
AI-assisted analysis of gitbutlerapp/gitbutler@caf1f223d3 (2026-08-20).
Data as JSON: /api/errors/c2dd313f5f0af98b.
Report an issue: GitHub.