xai-org/grok-build · error

git worktree add failed: {}

Error message

git worktree add failed: {}

What it means

execute_git_checkout_worktree runs `git worktree add` (with checkout) as a subprocess and, on non-zero exit status, bails with the full stderr. This surfaces git's own reason — branch conflicts, dirty/locked paths, invalid refs, missing commits, etc. — under a stable message prefix.

Source

Thrown at crates/codegen/xai-fast-worktree/src/worktree/execute.rs:1460

    // checkout.workers enables parallel checkout so git populates the
    // working tree using multiple threads.
    let output = git::checkout::git_command()
        .current_dir(&source_root)
        .arg("-c")
        .arg(format!("checkout.workers={workers}"))
        .args([
            "worktree",
            "add",
            "--detach",
            &dest.to_string_lossy(),
            git_ref,
        ])
        .output()
        .context("failed to run git worktree add")?;

    if !output.status.success() {
        let stderr = String::from_utf8_lossy(&output.stderr);
        anyhow::bail!("git worktree add failed: {}", stderr);
    }

    tracing::debug!(
        elapsed = ?start.elapsed(),
        "git worktree add (with checkout) complete"
    );

    // Get the commit.
    let commit = git::get_head_commit(dest).context("failed to get HEAD commit")?;

    tracing::info!(
        elapsed = ?start.elapsed(),
        commit = %commit,
        method = "git_checkout",
        "worktree created via git checkout"
    );

    Ok(CreateWorktreeResult {

View on GitHub (pinned to bc7f02eddd)

Solutions

  1. Run `git worktree add <dest> <ref>` manually in the source and read git's stderr for the concrete cause.
  2. Use a detached HEAD or a unique new branch when the branch is already checked out in another worktree.
  3. Remove a stale/non-empty destination directory before retrying.
  4. Run `git worktree prune` to clear stale worktree metadata, and check safe.directory/ownership config in CI.

Example fix

// before: reusing the same branch for many worktrees
let ref = "main";
// after: unique branch per worktree (or detached)
let ref = format!("wt/{}-{uuid}", task_name); // or "--detach HEAD"
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-checks before git worktree add
assert!(dest.parent().is_some(), "dest parent must exist");
assert!(!dest.exists(), "dest already exists: {dest:?}");
let rev = std::process::Command::new("git")
    .args(["rev-parse", "--verify", "--quiet", &ref])
    .current_dir(source)
    .status()
    .context("ref check failed")?;
assert!(rev.success(), "ref {ref:?} not found in source");

Try / catch

match create_worktree(&plan) {
    Err(e) if e.to_string().contains("is already used by worktree")
        || e.to_string().contains("already checked out") => {
        let mut plan = plan.clone();
        plan.reference = format!("--detach"); // or unique branch
        create_worktree(&plan).context("retry with unique ref failed")
    }
    other => other,
}

Prevention

When it happens

Trigger: Calling execute_git_checkout_worktree (projected-source path) when the target branch/commit is invalid or missing, a worktree with the same branch already exists ('already checked out'), the destination path already exists and is non-empty, or the source repo is corrupt/locked.

Common situations: Two worktrees created concurrently for the same branch (git forbids checking out the same branch twice); stale branch names after a force-push/rebase; leftover destination directory from a previously cancelled run; dubious-ownership repo in CI.

Related errors


AI-assisted analysis of xai-org/grok-build@bc7f02eddd (2026-08-31). Data as JSON: /api/errors/8142f8841f7297df. Report an issue: GitHub.