zed-industries/zed · error
git status failed: {stderr}
Error message
git status failed: {stderr} What it means
Repository status() runs `git status --porcelain=v1 --untracked-files=all --no-renames -z` and, when the process exits non-zero, wraps git's stderr in this message. The wrapper is not the cause: the appended stderr text names the actual git failure (ownership, permissions, lock files, bare repo, and so on).
Source
Thrown at crates/git/src/repository.rs:1843
return Ok(Vec::new());
}
if let Some(revision) = revisions.iter().find(|revision| revision.contains('\n')) {
anyhow::bail!(
"revision spec {revision:?} contains a newline and cannot be passed to git cat-file --batch"
);
}
let mut process = git
.build_command(&["cat-file", "--batch"])
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.kill_on_drop(true)
.spawn()?;
let mut stdin = BufWriter::new(process.stdin.take().context("no stdin")?);
let mut stdout = BufReader::new(process.stdout.take().context("no stdout")?);
let mut newline = [0u8; 1];
let mut header_bytes = Vec::new();
let mut results = Vec::with_capacity(revisions.len());
for rev in &revisions {
stdin.write_all(rev.as_bytes()).await?;
stdin.write_all(b"\n").await?;
stdin.flush().await?;
header_bytes.clear();
stdout.read_until(b'\n', &mut header_bytes).await?;
let header_line = String::from_utf8_lossy(&header_bytes);
let parts: Vec<&str> = header_line.trim().split(' ').collect();
match parts[..] {
[.., "missing"] => {
results.push(None);
}
[_, object_type, size_str] => {View on GitHub (pinned to 5a9b9558db)
Solutions
- Read the appended stderr first and act on that specific git message.
- For `detected dubious ownership`: `git config --global --add safe.directory /path/to/repo`.
- For `index.lock`: confirm no git process is running, then remove the stale `.git/index.lock`.
- For bare repos, target a worktree of the bare repository rather than the bare path itself.
- Verify permissions on `.git` and that the installed git supports `--porcelain=v1 -z`.
Defensive patterns
Strategy: try-catch
Validate before calling
// preflight before the first status call git.run(&["rev-parse", "--is-inside-work-tree"]).await?;
Try / catch
if let Err(e) = repo.status(&prefixes).await {
let msg = e.to_string();
if msg.contains("dubious ownership") {
// instruct user to run: git config --global --add safe.directory <path>
} else if msg.contains("index.lock") {
// stale lock: suggest cleanup after confirming no git process runs
} else {
return Err(e);
}
} Prevention
- Ensure the process runs as a user with read access to .git (avoid root-owned checkouts).
- Configure safe.directory for repositories not owned by the running user.
- Never kill git processes mid-status; a leftover index.lock breaks subsequent status calls.
- Surface git's stderr verbatim to users — the wrapper message alone is not diagnosable.
When it happens
Trigger: Any condition that makes `git status` fail in the worktree: `fatal: this operation must be run in a work tree` for a bare repository, `error: Insufficient permissions`, a stale or unreadable `.git/index.lock`, `fatal: detected dubious ownership in repository`, or a missing/corrupt HEAD ref.
Common situations: Repositories owned by another user or root (dubious ownership on newer git), repos on network mounts with permission problems, a leftover index.lock after a crashed git process, pointing tooling at a bare repo instead of a worktree, or extremely old git versions lacking porcelain v1 flags.
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
- git diff-tree failed: {stderr}
- git merge-base failed: {stderr}
- git worktree list failed: {stderr}
- git worktree add failed: {stderr}
- git log command failed with {}: {}
AI-assisted analysis of zed-industries/zed@5a9b9558db (2026-08-20).
Data as JSON: /api/errors/a12fe5f9de88f2d8.
Report an issue: GitHub.