Hmbown/CodeWhale · error · anyhow::Error
git worktree add failed for branch {} at {}{}{}
Error message
git worktree add failed for branch {} at {}{}{} What it means
provision_worktree() ran `git worktree add -b <branch> <path> <base>` inside repo_root and git exited non-zero. The message embeds the branch, the target path, and git's trimmed stderr, so the real cause is in the appended detail. Typical causes are a branch that already exists, a non-empty target directory, or a bad base ref.
Source
Thrown at crates/lane/src/worktree.rs:60
let base = spec.base_ref.as_deref().unwrap_or("HEAD");
// Capture git output instead of inheriting the caller's terminal. Runtime
// callers include the raw-mode TUI launch screen, where even one inherited
// progress/error line corrupts the alternate-screen buffer.
let output = Command::new("git")
.current_dir(&spec.repo_root)
.args([
"worktree",
"add",
"-b",
&spec.branch,
&spec.path.to_string_lossy(),
base,
])
.output()
.context("git worktree add")?;
if !output.status.success() {
let detail = String::from_utf8_lossy(&output.stderr).trim().to_string();
bail!(
"git worktree add failed for branch {} at {}{}{}",
spec.branch,
spec.path.display(),
if detail.is_empty() { "" } else { ": " },
detail
);
}
Ok(ProvisionedWorktree {
path: spec.path.clone(),
branch: spec.branch.clone(),
})
}
/// Remove a worktree when TTL has expired (or immediately when TTL is 0).
///
/// `stopped_at` is RFC3339. When `ttl_secs` is `None`, no cleanup is performed.
pub fn remove_worktree_if_expired(
worktree_path: &Path,View on GitHub (pinned to 0c42157ee5)
Solutions
- Read the stderr detail in the message first — 'already exists', 'already registered', and 'not a valid ref' each have different fixes
- If the branch exists: delete it (`git branch -D <branch>`) or reuse the existing worktree instead of provisioning a new one
- Run `git worktree prune` and remove the stale target directory, then retry with the same spec
- Validate base_ref first with `git rev-parse --verify <base_ref>^{commit}` before provisioning
- Generate collision-free branch names (e.g. include a lane id or timestamp) when re-provisioning is expected
Example fix
// before
let wt = provision_worktree(&spec)?;
// after: recover from the two common collisions
let wt = match provision_worktree(&spec) {
Ok(wt) => wt,
Err(err) if err.to_string().contains("already exists") => {
Command::new("git")
.args(["branch", "-D", &spec.branch])
.current_dir(&spec.repo_root)
.status()?;
provision_worktree(&spec)?
}
Err(err) => return Err(err),
}; Defensive patterns
Strategy: try-catch
Validate before calling
// Pre-flight the two common causes:
let out = Command::new("git").current_dir(&spec.repo_root)
.args(["rev-parse", "--verify", &format!("{}^{{commit}}", base)])
.output()?;
if !out.status.success() { bail!("base ref {base} does not resolve"); }
if spec.path.exists() && std::fs::read_dir(&spec.path)?.next().is_some() {
bail!("worktree path {} not empty", spec.path.display());
} Try / catch
match provision_worktree(&spec) {
Ok(wt) => Ok(wt),
Err(err) => {
let msg = format!("{err:#}");
if msg.contains("already exists") || msg.contains("already registered") {
// branch or path collision: clean up and retry once
cleanup_branch_and_path(&spec)?;
provision_worktree(&spec)
} else {
Err(err)
}
}
} Prevention
- Include a lane id in generated branch names so re-provisioning cannot collide
- Run `git worktree prune` before provisioning in recovery flows
- Always resolve base_ref to a commit hash before passing it
When it happens
Trigger: Re-provisioning a lane whose branch already exists locally; specifying a worktree path that already contains files (including a stale worktree from a crashed prior run); passing base_ref that names a ref that does not exist (e.g. origin/feature after a remote rename); running while HEAD is unborn in a fresh `git init` clone; repo_root pointing at a directory without a valid .git.
Common situations: Retry-after-crash flows that recreate the same lane/branch name; parallel lanes colliding on generated branch names; shallow or bare checkouts where the expected base ref is absent; leftover worktree metadata after a force-deleted directory (needs `git worktree prune`).
Understand the failure class
Background: "git command failed": what it means when a tool shells out to git and git exits non-zero — this error's family across 21 libraries.
Related errors
- worktree branch must not be empty
- repo root does not exist: {}
- --worktree-repo and --branch must be provided together
- git diff failed: {}
- tmux attach unavailable
AI-assisted analysis of Hmbown/CodeWhale@0c42157ee5 (2026-08-20).
Data as JSON: /api/errors/4933b34de0e873d7.
Report an issue: GitHub.