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 onView on GitHub (pinned to bc7f02eddd)
Solutions
- 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.
- 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).
- If the ref is invalid, verify it exists with `git rev-parse <ref>` in the worktree before calling snapshot/test_worktree_at_ref.
- Check ownership/permissions: run `git config --global --add safe.directory <path>` or fix ownership (`chown -R`) if 'dubious ownership' appears in stderr.
- 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
- Read the stderr embedded in the message — it names the exact git failure.
- Remove stale .git/index.lock files after crashed git processes.
- Resolve and rev-parse refs before passing them to snapshot/test helpers.
- Add safe.directory config when running across user boundaries.
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
- git worktree add failed: {}
- no .git file or directory found at {}
- worktree creation task failed: {e}
- git command failed
- the probe's output did not drain within {DRAIN_GRACE:?}
AI-assisted analysis of xai-org/grok-build@bc7f02eddd (2026-08-31).
Data as JSON: /api/errors/934c0eb4b67474e2.
Report an issue: GitHub.