nikivdev/code · error

claude returned empty commit message

Error message

claude returned empty commit message

What it means

Thrown when the `claude` CLI exits successfully but its stdout, after trimming, is empty — no commit message was produced. The code deliberately distinguishes this from a process failure to give a clearer message.

Source

Thrown at src/commit.rs:12762

    if !status.is_empty() {
        prompt.push_str("\n\nGit status:\n");
        prompt.push_str(status);
    }

    let output = Command::new("claude")
        .args(["-p", &prompt])
        .output()
        .context("failed to run claude for commit message")?;

    if !output.status.success() {
        let stderr = String::from_utf8_lossy(&output.stderr);
        bail!("claude failed: {}", stderr.trim());
    }

    let message = String::from_utf8_lossy(&output.stdout).trim().to_string();

    if message.is_empty() {
        bail!("claude returned empty commit message");
    }

    Ok(trim_quotes(&message))
}

/// Generate commit message using Rise daemon (local AI proxy).
fn generate_commit_message_rise(
    diff: &str,
    status: &str,
    truncated: bool,
    model: &str,
) -> Result<String> {
    let mut user_prompt =
        String::from("Write a git commit message for the staged changes.\n\nGit diff:\n");
    user_prompt.push_str(diff);

    if truncated {
        user_prompt.push_str("\n\n[Diff truncated]");

View on GitHub (pinned to a747e741ae)

Solutions

  1. Run `claude -p "say hi"` and confirm it prints text to stdout.
  2. Re-authenticate with `claude login`.
  3. Check for shell aliases/wrappers intercepting claude output (`type claude`).
  4. Retry with a smaller diff/staged change set in case the model returned empty on a huge prompt.

Example fix

// before
if message.is_empty() {
    bail!("claude returned empty commit message");
}
// after
if message.is_empty() {
    bail!("claude returned empty commit message (stderr: {})", String::from_utf8_lossy(&output.stderr).trim());
}
Defensive patterns

Strategy: fallback

Validate before calling

// Preflight: confirm claude produces non-empty stdout
let out = std::process::Command::new("claude").args(["-p", "ping"]).output()?;
if String::from_utf8_lossy(&out.stdout).trim().is_empty() {
    return Err(anyhow!("claude CLI produces empty output"));
}

Type guard

fn is_non_empty_message(s: &str) -> bool { !s.trim().is_empty() }

Try / catch

match result {
    Err(e) if e.to_string().contains("empty commit message") => {
        eprintln!("claude returned nothing; check auth/alias, falling back");
        fallback_to_manual_message()
    }
    other => other,
}

Prevention

When it happens

Trigger: `claude -p <prompt>` exits 0 but prints nothing: silent auth degradation, output redirected elsewhere, model refusal producing no text, or stdout swallowed by a wrapper/alias.

Common situations: A shell alias or wrapper around `claude` consumes stdout; claude session expired so it warns on stderr but exits 0; model returns an empty response on a very large diff prompt.

Related errors


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