affaan-m/ECC · error · anyhow::Error
git status failed: {stderr}
Error message
git status failed: {stderr} What it means
git_status_entries shells out to `git -C <worktree.path> status --porcelain=v1 --untracked-files=all` and re-throws git's stderr when the process exits non-zero. It is the foundation for nearly every status-driven operation (staging, commit readiness, health), so a failure here cascades upstream. The error message is git's own stderr, so the underlying cause is usually visible in the message text.
Source
Thrown at ecc2/src/worktree/mod.rs:283
if parts.is_empty() {
Ok(Some(format!("Clean relative to {}", worktree.base_branch)))
} else {
Ok(Some(parts.join(" | ")))
}
}
pub fn git_status_entries(worktree: &WorktreeInfo) -> Result<Vec<GitStatusEntry>> {
let output = Command::new("git")
.arg("-C")
.arg(&worktree.path)
.args(["status", "--porcelain=v1", "--untracked-files=all"])
.output()
.context("Failed to load git status entries")?;
if !output.status.success() {
let stderr = String::from_utf8_lossy(&output.stderr);
anyhow::bail!("git status failed: {stderr}");
}
Ok(String::from_utf8_lossy(&output.stdout)
.lines()
.filter_map(parse_git_status_entry)
.collect())
}
pub fn stage_path(worktree: &WorktreeInfo, path: &str) -> Result<()> {
let output = Command::new("git")
.arg("-C")
.arg(&worktree.path)
.args(["add", "--"])
.arg(path)
.output()
.with_context(|| format!("Failed to stage {}", path))?;
if output.status.success() {
Ok(())View on GitHub (pinned to 01e15490f0)
Solutions
- Check that `worktree.path` is still an existing directory before calling (e.g. `if !worktree.path.is_dir() { ... }`).
- Remove a stale `.git/index.lock` if present: `rm -f <repo>/.git/index.lock` after confirming no git process is running.
- Re-resolve the WorktreeInfo via create_for_session / the session store if the worktree was recreated or its path changed.
- Verify filesystem permissions and that the path is inside a repo (`git -C <path> rev-parse --is-inside-work-tree`).
Example fix
// before
let entries = git_status_entries(&worktree)?;
// after
if !worktree.path.is_dir() {
anyhow::bail!("worktree path missing: {}", worktree.path.display());
}
let entries = git_status_entries(&worktree)?; Defensive patterns
Strategy: validation
Validate before calling
use std::path::Path;
fn ensure_worktree_usable(path: &Path) -> anyhow::Result<()> {
if !path.is_dir() {
anyhow::bail!("worktree path is not a directory: {}", path.display());
}
let lock = path.join(".git").join("index.lock");
// Also handle a gitdir file for linked worktrees
if lock.exists() {
anyhow::bail!("stale index.lock present: {}", lock.display());
}
Ok(())
}
// call before git_status_entries
ensure_worktree_usable(&worktree.path)?;
let entries = git_status_entries(&worktree)?; Try / catch
match git_status_entries(&worktree) {
Ok(entries) => { /* proceed */ }
Err(e) => {
// Distinguish spawn-failure (.context) from git-failure (bail!).
if format!("{e:#}").contains("git status failed") {
// surface to user as 'repo/worktree unusable'
}
return Err(e);
}
} Prevention
- Never delete worktrees manually; always go through the worktree manager so WorktreeInfo handles stay valid.
- Hold at most one concurrent git process per worktree to avoid index.lock races.
- Refresh WorktreeInfo from the session store at the start of each user action.
- Run the app as the user that owns the worktree to avoid permission denials.
When it happens
Trigger: Calling git_status_entries, has_staged_changes, health, or diff_file_preview on a WorktreeInfo whose path no longer exists, is not inside a git repository, has a stale `.git/index.lock`, or is unreadable by the current process. Also triggered when the worktree was pruned/deleted out of band while a session still holds a stale WorktreeInfo handle.
Common situations: Worktree removed manually (rm -rf) or via `git worktree prune` while the session keeps an old WorktreeInfo; a previous git process crashed and left `.git/index.lock`; CI/container runs as a different uid than the worktree owner; the worktree path was a symlink whose target moved.
Related errors
- git worktree add failed: {stderr}
- git add failed for {path}: {stderr}
- git reset failed for {path}: {stderr}
- git restore failed for {}: {stderr}
- git commit failed: {stderr}
AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13).
Data as JSON: /api/errors/4110b9aba1dee815.
Report an issue: GitHub.