nikivdev/code · error

git diff --cached --name-only failed

Error message

git diff --cached --name-only failed

What it means

`staged_gitignore_files` shells out to `git diff --cached --name-only --diff-filter=ACMR` inside the repository root to list staged .gitignore files. When the subprocess exits with a non-zero status, the function bails with this message. This is not a parse error of the diff output itself — it means git itself rejected the invocation.

Source

Thrown at src/gitignore_policy.rs:459

            if line.starts_with(' ') {
                line_no = line_no.saturating_add(1);
            }
        }
    }

    Ok(violations)
}

fn staged_gitignore_files(repo_root: &Path) -> Result<Vec<String>> {
    let output = Command::new("git")
        .current_dir(repo_root)
        .args(["diff", "--cached", "--name-only", "--diff-filter=ACMR"])
        .output()
        .context("failed to list staged files")?;

    if !output.status.success() {
        bail!("git diff --cached --name-only failed")
    }

    Ok(String::from_utf8_lossy(&output.stdout)
        .lines()
        .map(str::trim)
        .filter(|s| s.ends_with(".gitignore"))
        .map(|s| s.to_string())
        .collect())
}

fn inspect_repo_gitignores(repo_root: &Path, policy: &GitignorePolicy) -> Result<Vec<Violation>> {
    let blocked = blocked_lookup(policy);
    let files = list_gitignore_files(repo_root);
    let mut out = Vec::new();

    for file in files {
        let content = fs::read_to_string(&file)
            .with_context(|| format!("failed to read {}", file.display()))?;

View on GitHub (pinned to a747e741ae)

Solutions

  1. Verify the process runs inside a valid git repository: `git -C <repo_root> rev-parse --is-inside-work-tree`
  2. Check for a stale lock file and remove it: `rm <repo_root>/.git/index.lock` (only when no git process is running)
  3. If on a CI container, add the checkout dir to safe.directory: `git config --global --add safe.directory <repo_root>`
  4. Run the exact command manually to see git's real error: `git -C <repo_root> diff --cached --name-only --diff-filter=ACMR`

Example fix

// before
let output = Command::new("git")
    .args(["diff", "--cached", "--name-only", "--diff-filter=ACMR"])
    .current_dir(repo_root)
    .output()
    .context("failed to list staged files")?;
// after
let output = Command::new("git")
    .args(["-C", repo_root.to_str().unwrap(), "rev-parse", "--is-inside-work-tree"])
    .output()?;
anyhow::ensure!(output.status.success(), "not a git repo: {}", repo_root.display());
let output = Command::new("git")
    .args(["diff", "--cached", "--name-only", "--diff-filter=ACMR"])
    .current_dir(repo_root)
    .output()
    .context("failed to list staged files")?;
Defensive patterns

Strategy: try-catch

Validate before calling

let ok = Command::new("git")
    .args(["-C", repo_root.to_str().unwrap(), "rev-parse", "--is-inside-work-tree"])
    .output()
    .map(|o| o.status.success())
    .unwrap_or(false);
if !ok { anyhow::bail!("{} is not a usable git repository", repo_root.display()); }

Type guard

fn is_git_repo(repo_root: &Path) -> bool {
    repo_root.join(".git").exists()
        && Command::new("git")
            .args(["-C", repo_root.to_str().unwrap(), "rev-parse", "--git-dir"])
            .output()
            .map(|o| o.status.success())
            .unwrap_or(false)
}

Try / catch

match staged_gitignore_files(repo_root) {
    Ok(files) => process(files),
    Err(e) if e.to_string().contains("git diff --cached") => {
        eprintln!("git unavailable/index locked: {e:#}");
        eprintln!("hint: check for .git/index.lock or run outside a repo");
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Running `git diff --cached` while not inside a git repository or in a repo whose .git dir is unreadable; a corrupt or locked git index (e.g. stale index.lock); a git version that does not support the flags; git exiting due to safe.directory ownership restrictions.

Common situations: Calling this helper from outside a git repo (repo_root mis-detected or a parent path passed in); running during a git operation that holds an index lock (rebase/merge in progress); CI containers where the checkout is owned by a different user than the process.

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


AI-assisted analysis of nikivdev/code@a747e741ae (2026-09-01). Data as JSON: /api/errors/e3fbd8372b563a26. Report an issue: GitHub.