affaan-m/ECC · critical · anyhow::Error

git rev-parse failed: {stderr}

Error message

git rev-parse failed: {stderr}

What it means

Right after a successful `git commit`, commit_staged runs `git rev-parse --short HEAD` to capture the new commit's short hash. A non-zero exit at this point is highly unusual: the commit just succeeded, so HEAD should resolve. Failure usually indicates repository corruption or that the commit step did not actually advance HEAD despite exiting zero.

Source

Thrown at ecc2/src/worktree/mod.rs:483

        .arg("-C")
        .arg(&worktree.path)
        .args(["commit", "-m", message])
        .output()
        .context("Failed to create commit")?;
    if !output.status.success() {
        let stderr = String::from_utf8_lossy(&output.stderr);
        anyhow::bail!("git commit failed: {stderr}");
    }

    let rev_parse = Command::new("git")
        .arg("-C")
        .arg(&worktree.path)
        .args(["rev-parse", "--short", "HEAD"])
        .output()
        .context("Failed to resolve commit hash")?;
    if !rev_parse.status.success() {
        let stderr = String::from_utf8_lossy(&rev_parse.stderr);
        anyhow::bail!("git rev-parse failed: {stderr}");
    }

    Ok(String::from_utf8_lossy(&rev_parse.stdout)
        .trim()
        .to_string())
}

pub fn latest_commit_subject(worktree: &WorktreeInfo) -> Result<String> {
    let output = Command::new("git")
        .arg("-C")
        .arg(&worktree.path)
        .args(["log", "-1", "--pretty=%s"])
        .output()
        .context("Failed to read latest commit subject")?;
    if !output.status.success() {
        let stderr = String::from_utf8_lossy(&output.stderr);
        anyhow::bail!("git log failed: {stderr}");
    }

View on GitHub (pinned to 01e15490f0)

Solutions

  1. Run `git -C <path> fsck --no-dangling` to detect corruption.
  2. Check disk space on the volume holding the repo.
  3. Re-read HEAD with `git -C <path> log -1 --pretty=%H` to confirm the commit landed; if not, retry the commit.
  4. Surface the rev-parse stderr verbatim — it usually points at the corruption type.
Defensive patterns

Strategy: try-catch

Validate before calling

// There is no caller-side validation that prevents repository corruption.
// Best pre-check: confirm the commit actually landed before trusting it.
fn head_short(worktree: &WorktreeInfo) -> anyhow::Result<String> {
    let out = std::process::Command::new("git")
        .arg("-C").arg(&worktree.path)
        .args(["log", "-1", "--pretty=%h"])
        .output()?;
    if !out.status.success() {
        anyhow::bail!("HEAD did not resolve after commit");
    }
    Ok(String::from_utf8_lossy(&out.stdout).trim().to_string())
}

Try / catch

match commit_staged(&worktree, msg) {
    Ok(hash) => Ok(hash),
    Err(e) if format!("{e:#}").contains("rev-parse failed") => {
        // fall back to `git log -1 --pretty=%h`; if that also fails, run fsck
        Err(e).with_context(|| "post-commit rev-parse failed; run `git fsck`")
    }
    Err(e) => Err(e),
}

Prevention

When it happens

Trigger: The commit's pre-commit hook performed a reset/amend that left HEAD detached or unborn; the object database was corrupted by disk pressure between commit and rev-parse; a concurrent process moved HEAD to a state where `--short` formatting fails (rare).

Common situations: Disk-full during commit object write; aggressive background GC packed the new object away inconsistently; sandboxed filesystem that loses the new loose object.

Related errors


AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13). Data as JSON: /api/errors/b22ef6d221b5da20. Report an issue: GitHub.