nikivdev/code · error

OpenRouter returned empty commit message

Error message

OpenRouter returned empty commit message

What it means

Thrown when the OpenRouter API returned HTTP success but the first choice's message content is empty or absent, so the default `unwrap_or_default()` yields an empty string.

Source

Thrown at src/commit.rs:12879

                role: "user".to_string(),
                content: user_prompt,
            },
        ],
        temperature: 0.3,
    };

    let parsed: ChatResponse = openrouter_chat_completion_with_retry(&client, &api_key, &body)
        .context("OpenRouter request failed")?;

    let message = parsed
        .choices
        .first()
        .and_then(|c| c.message.as_ref())
        .map(|m| m.content.trim().to_string())
        .unwrap_or_default();

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

    Ok(trim_quotes(&message))
}

fn generate_commit_message(
    api_key: &str,
    diff: &str,
    status: &str,
    truncated: bool,
) -> 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 to fit within prompt]");
    }

View on GitHub (pinned to a747e741ae)

Solutions

  1. Retry with a different OpenRouter model to rule out a degraded model.
  2. Reduce the diff/prompt size to stay within the model's context window.
  3. Log the raw JSON response and check `finish_reason` (content_filter, length) and confirm `choices[0].message.content` is populated.
  4. Verify the `ChatResponse` struct still matches OpenRouter's current API schema.
Defensive patterns

Strategy: fallback

Validate before calling

// Validate model id is configured before calling OpenRouter
if model_id.is_empty() {
    return Err(anyhow!("OpenRouter model id must be set"));
}

Type guard

fn openrouter_choice_has_content(resp: &ChatResponse) -> bool {
    resp.choices.first()
        .and_then(|c| c.message.as_ref())
        .map(|m| !m.content.trim().is_empty())
        .unwrap_or(false)
}

Try / catch

match result {
    Err(e) if e.to_string().contains("OpenRouter returned empty") => {
        eprintln!("OpenRouter gave empty content; retrying with another model");
        fallback_to_alternate_model()
    }
    other => other,
}

Prevention

When it happens

Trigger: OpenRouter responds 200 with `choices[0].message.content` missing, null, or whitespace-only — e.g. the routed model returned an empty completion, a content-filter stop, or an unexpected response shape.

Common situations: Selected OpenRouter model is deprecated/degraded; content filter suppressed the output; large diff prompt hit a token limit causing truncated/empty output; API schema change not reflected in the `ChatResponse` struct.

Related errors


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