xai-org/grok-build · error

git {shown} failed in {}: {}

Error message

git {shown} failed in {}: {}

What it means

git_capture_in runs a git command (with a snapshot timeout) inside a worktree and fails if git exits non-zero. The message embeds the displayed command, the worktree path, and git's stderr, so it wraps any git failure during snapshot/checkout operations such as `git status`, `git add`, or `git write-tree`. It signals that the repository state or invocation was rejected by git itself, not by this library.

Source

Thrown at crates/codegen/xai-fast-worktree/src/git/checkout.rs:212

    // Same reason the probes do it: the snapshot runs unattended, and the
    // hooks are the worktree's own.
    cmd.current_dir(worktree_path)
        .args(["-c", &format!("core.hooksPath={NO_HOOKS}")])
        .args(args);
    // Before the caller's own, which is what carries the scratch index: the
    // snapshot has to read the configuration the gate's probes read, or the
    // two halves judge different repositories.
    super::probe::forget_inherited_git_environment(&mut cmd);
    for &(key, val) in envs {
        cmd.env(key, val);
    }

    let shown = display_args(args);
    let output = super::probe::run_with_timeout(cmd, Vec::new(), SNAPSHOT_TIMEOUT)
        .with_context(|| format!("failed to run git {shown} in {}", worktree_path.display()))?;

    if !output.status.success() {
        anyhow::bail!(
            "git {shown} failed in {}: {}",
            worktree_path.display(),
            String::from_utf8_lossy(&output.stderr)
        );
    }

    Ok(String::from_utf8_lossy(&output.stdout).trim().to_string())
}

/// Render git args for an error/context message (paths shown lossily).
fn display_args<S: AsRef<OsStr>>(args: &[S]) -> String {
    args.iter()
        .map(|arg| arg.as_ref().to_string_lossy().into_owned())
        .collect::<Vec<String>>()
        .join(" ")
}

/// Git config overrides (`-c key=val`, applied before the subcommand) used on

View on GitHub (pinned to bc7f02eddd)

Solutions

  1. Read the stderr portion of the message first — it contains git's own diagnosis (e.g. 'index.lock exists', 'bad object <ref>') and fix that specific cause.
  2. If it's an index.lock error, remove the stale lock file: git rm-free fix is `rm <worktree>/.git/index.lock` (verify no git process is running).
  3. If the ref is invalid, verify it exists with `git rev-parse <ref>` in the worktree before calling snapshot/test_worktree_at_ref.
  4. Check ownership/permissions: run `git config --global --add safe.directory <path>` or fix ownership (`chown -R`) if 'dubious ownership' appears in stderr.
  5. Verify the worktree's .git linkage is intact (`cat .git` points to the repo's .git/worktrees/<name>) or recreate the worktree.

Example fix

// before: passing a ref that may not exist
let out = test_worktree_at_ref(worktree_path, "origin/feature-branch")?;
// after: resolve and validate the ref first
let out = git_capture_in(worktree_path, &["rev-parse", "--verify", "origin/feature-branch"])
    .ok()
    .and_then(|_| test_worktree_at_ref(worktree_path, "origin/feature-branch"))?;
Defensive patterns

Strategy: try-catch

Validate before calling

// before calling snapshot/test_worktree_at_ref, verify repo health
let probe = std::process::Command::new("git")
    .args(["rev-parse", "--verify", ref_name])
    .current_dir(worktree_path)
    .output()?;
if !probe.status.success() {
    anyhow::bail!("ref {} unavailable in {}: {}", ref_name, worktree_path.display(),
        String::from_utf8_lossy(&probe.stderr));
}

Try / catch

match snapshot_git(path) {
    Err(e) if e.to_string().contains("index.lock") => {
        std::fs::remove_file(path.join(".git/index.lock")).ok();
        retry_with_backoff(|| snapshot_git(path))
    }
    Err(e) if e.to_string().contains("bad object") => bail!("ref pruned; re-resolve before snapshotting"),
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling snapshot_git, test_worktree_at_ref, or rehydrate/snapshot helpers when the underlying git command exits non-zero: e.g. corrupted index/lock files, invalid ref passed to test_worktree_at_ref, .git directory missing or unreadable, or git hooks/config causing failure. Callers include snapshot_git, test_worktree_at_ref, and the worktree snapshot tests.

Common situations: A leftover .git/index.lock blocking git status; a caller passing a nonexistent or pruned ref (e.g. after force-push or GC); running as a different user so git's safe.directory check rejects the repo; truncated or corrupt .git dir on NFS worktrees; PATH lacking a working git binary or git failing due to SIGPIPE on huge trees.

Related errors


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