affaan-m/ECC · error · anyhow::Error
git commit failed: {stderr}
Error message
git commit failed: {stderr} What it means
commit_staged runs `git commit -m <message>` after the pre-flight checks pass. A non-zero exit re-throws git's stderr. The message has already passed the empty-check and staged-changes check, so failure here is typically a hook, signing, or identity problem.
Source
Thrown at ecc2/src/worktree/mod.rs:472
pub fn commit_staged(worktree: &WorktreeInfo, message: &str) -> Result<String> {
let message = message.trim();
if message.is_empty() {
anyhow::bail!("commit message cannot be empty");
}
if !has_staged_changes(worktree)? {
anyhow::bail!("no staged changes to commit");
}
let output = Command::new("git")
.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())
}
View on GitHub (pinned to 01e15490f0)
Solutions
- Read the stderr in the bail message — it usually names the exact hook or signing failure; fix that root cause first.
- Ensure `user.name` and `user.email` are set for the environment (`git config user.email`).
- If a pre-commit hook is expected to fail, surface its output to the user instead of opaque retry.
- Re-run `has_staged_changes` immediately before commit to close the race window.
Example fix
// before
let hash = commit_staged(&worktree, msg)?;
// after
match commit_staged(&worktree, msg) {
Ok(hash) => Ok(hash),
Err(e) => Err(e).with_context(|| "commit rejected by git (hook/signing/identity); see stderr above"),
} Defensive patterns
Strategy: try-catch
Validate before calling
// Pre-flight: identity must be configured or git refuses to commit.
fn git_identity_ok(worktree: &WorktreeInfo) -> bool {
let out = std::process::Command::new("git")
.arg("-C").arg(&worktree.path)
.args(["config", "user.email"])
.output();
matches!(out, Ok(o) if o.status.success() && !o.stdout.is_empty())
}
if !git_identity_ok(&worktree) {
anyhow::bail!("set git user.email and user.name before committing");
}
let hash = commit_staged(&worktree, msg)?; Try / catch
match commit_staged(&worktree, msg) {
Ok(hash) => Ok(hash),
Err(e) => {
let m = format!("{e:#}");
if m.contains("hook") || m.contains("pre-commit") {
// surface hook output verbatim; do not retry
} else if m.contains("user.email") || m.contains("user.name") {
// prompt to configure identity
} else if m.contains("index.lock") {
// clear lock and retry once
}
Err(e)
}
} Prevention
- Always set `user.name` and `user.email` (global or repo-local) before the first commit.
- Treat pre-commit hook failures as user-visible errors and show the hook output.
- Hold a single in-flight commit per worktree to avoid index.lock contention.
- If signing commits, ensure gpg/ssh signing is configured and the agent is unlocked.
When it happens
Trigger: A pre-commit or commit-msg hook exits non-zero; GPG signing requested but no usable key/gpg-agent; `user.email`/`user.name` not configured and git refuses to synthesize an identity; `.git/index.lock` contention; a concurrent commit consumed the staged changes between the check and the commit.
Common situations: husky/lefthook running lint+test that fails; CI environment with no `git config --global user.email`; GPG card unplugged; two sessions committing the same worktree simultaneously.
Related errors
- git rev-parse failed: {stderr}
- git worktree add failed: {stderr}
- git status failed: {stderr}
- git add failed for {path}: {stderr}
- git reset failed for {path}: {stderr}
AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13).
Data as JSON: /api/errors/b3c9284056473398.
Report an issue: GitHub.