xai-org/grok-build · error

git command failed

Error message

git command failed

What it means

`git_cli` shells out to `git --no-optional-locks <args>` in a working directory and returns trimmed stdout. When git exits non-zero, the error message is the scrubbed stderr text; if git printed nothing on stderr, this generic fallback message "git command failed" is used instead. It surfaces for any git subcommand failure invoked through the session VCS layer (get_branch, get_upstream, get_remote_url, ahead/behind, status).

Source

Thrown at crates/codegen/xai-grok-workspace/src/session/git.rs:98

                error = %e,
                error_kind = ?e.kind(),
                cwd = %cwd.display(),
                "git_cli: Command::output() FAILED (spawn error)"
            );
            return Err(e.into());
        }
    };
    if output.status.success() {
        let stdout = String::from_utf8_lossy(&output.stdout).trim().to_string();
        tracing::debug!(exit_code = 0, stdout_len = stdout.len(), "git_cli success");
        Ok(stdout)
    } else {
        let stderr = scrub_git_output(&String::from_utf8_lossy(&output.stderr))
            .trim()
            .to_string();
        let code = output.status.code();
        tracing::debug!(exit_code = ?code, stderr = %stderr, "git_cli failed");
        Err(anyhow::anyhow!(
            "{}",
            if stderr.is_empty() {
                "git command failed"
            } else {
                &stderr
            }
        ))
    }
}
/// Mutating [`git_cli`]: bump the gate epoch after the attempt. Failed
/// commands can still change the repo (`pull --rebase` conflicts, partial
/// checkout); skipping invalidate would keep pre-mutation snapshots.
async fn git_cli_mut(cwd: &Path, args: &[&str]) -> Result<String> {
    let result = git_cli(cwd, args).await;
    super::git_gate::invalidate(cwd);
    result
}
/// Run a jj CLI command and return stdout on success, or error with stderr.

View on GitHub (pinned to bc7f02eddd)

Solutions

  1. Run the same git command manually in the reported cwd (`git -C <cwd> status`) to see the real failure.
  2. Confirm the directory is inside a git work tree (`git -C <cwd> rev-parse --show-toplevel`).
  3. Remove a stale `.git/index.lock` if concurrent processes left one behind.
  4. Re-run with `GIT_TRACE=1` to capture the underlying git error that produced empty stderr.
Defensive patterns

Strategy: try-catch

Validate before calling

// Check git availability and repo presence before invoking git_cli
fn git_repo_ok(cwd: &Path) -> bool {
    cwd.join(".git").exists()
        || std::process::Command::new("git")
            .arg("-C").arg(cwd)
            .arg("rev-parse").arg("--git-dir")
            .output().map(|o| o.status.success()).unwrap_or(false)
}

Try / catch

// Empty-stderr failures hide the real cause; rerun the command manually for diagnosis
match git_cli(cwd, &["rev-parse", "--abbrev-ref", "HEAD"]).await {
    Ok(branch) => use_branch(branch),
    Err(e) if e.to_string() == "git command failed" => {
        eprintln!("git failed in {} with no stderr — run `git -C {cwd:?} status` manually", cwd.display());
    }
    Err(e) => eprintln!("git: {e}"), // stderr text is embedded in the message
}

Prevention

When it happens

Trigger: Any `git_cli`/`git_cli_mut` call where the git process exits non-zero with empty stderr: missing repo (`.git` absent) for some commands, bad object refs, index.lock contention producing no stderr, or git killed by a signal (no exit code, empty stderr).

Common situations: Running in a directory that is not a git repository or a bare repo where the query fails; detached/corrupted .git; git hooks or credential helpers failing silently; concurrent operations holding the index; PATH missing git for subshells (though that is usually a spawn error, not this one).

Related errors


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