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

commit message cannot be empty

Error message

commit message cannot be empty

What it means

commit_staged trims the supplied message and bails if the result is empty. This is the first of two pre-flight checks (the second is staged-changes presence). An empty commit message is almost always a UI or caller bug rather than a user intent.

Source

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

            if entry.unstaged {
                anyhow::bail!(
                    "cannot reset a staged hunk while the file also has unstaged changes; unstage it first"
                );
            }
            git_apply_patch(
                &worktree.path,
                &["-R", "--index"],
                &hunk.patch,
                "reset selected staged hunk",
            )
        }
    }
}

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")

View on GitHub (pinned to 01e15490f0)

Solutions

  1. Validate `message.trim().is_empty()` in the UI/command layer and block submission with a user-facing error.
  2. Provide a sensible default or template the caller must override before reaching commit_staged.
  3. Strip nothing inside commit_staged — trim happens there; ensure upstream code does not pre-strip to empty.

Example fix

// before
let hash = commit_staged(&worktree, &raw_input)?;

// after
let trimmed = raw_input.trim();
if trimmed.is_empty() {
    return Err(anyhow!("a commit message is required"));
}
let hash = commit_staged(&worktree, trimmed)?;
Defensive patterns

Strategy: validation

Validate before calling

fn ensure_commit_message(msg: &str) -> anyhow::Result<&str> {
    let trimmed = msg.trim();
    if trimmed.is_empty() {
        anyhow::bail!("commit message is required");
    }
    Ok(trimmed)
}

let msg = ensure_commit_message(raw)?;
let hash = commit_staged(&worktree, msg)?;

Try / catch

match commit_staged(&worktree, raw) {
    Ok(hash) => Ok(hash),
    Err(e) if format!("{e}").contains("cannot be empty") => {
        // prompt user for a message and retry
        Err(e)
    }
    Err(e) => Err(e),
}

Prevention

When it happens

Trigger: Passing `""`, `" "`, `"\n\n"`, or a string of only whitespace to commit_staged. Happens when the commit-message textbox was never populated, the message field was bound to the wrong input, or a template was stripped to nothing by a sanitizer.

Common situations: Form submission with no message typed; AI-generated commit message came back empty; trimming/sanitizing layer reduced a placeholder template to whitespace.

Related errors


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