nikivdev/code · error

OpenRouter returned empty review output

Error message

OpenRouter returned empty review output

What it means

The AI code-review feature calls OpenRouter's chat-completions API and expects a non-empty assistant message. After the HTTP request succeeds, the tool extracts choices[0].message.content, trims it, and throws this error if the result is an empty string. It means OpenRouter returned a 200 response whose payload contained no usable text.

Source

Thrown at src/commit.rs:6217

    let start = std::time::Instant::now();

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

    info!(
        elapsed_ms = start.elapsed().as_millis() as u64,
        "OpenRouter responded"
    );

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

    if output.is_empty() {
        bail!("OpenRouter returned empty review output");
    }

    println!("{}", output);

    let mut review_json = parse_review_json(&output);
    let future_tasks = review_json
        .as_ref()
        .map(|json| normalize_future_tasks(&json.future_tasks))
        .unwrap_or_default();
    let mut summary = review_json.as_ref().and_then(|r| r.summary.clone());
    let quality = review_json.as_mut().and_then(|r| r.quality.take());
    let (mut issues_found, mut issues) = if let Some(ref json) = review_json {
        (json.issues_found, json.issues.clone())
    } else {
        let lowered = output.to_lowercase();
        let has_issues = lowered.contains("bug")
            || lowered.contains("issue")
            || lowered.contains("error")

View on GitHub (pinned to a747e741ae)

Solutions

  1. Re-run the review; transient empty completions often succeed on retry
  2. Switch to a different/more capable model via the model config
  3. Verify the OpenRouter API key and account quota at openrouter.ai
  4. Log the raw response body to confirm whether choices/content are missing
  5. Reduce the diff size sent in the prompt so the model can produce output

Example fix

// before
let output = parsed.choices.first()
    .and_then(|c| c.message.as_ref())
    .map(|m| m.content.trim().to_string())
    .unwrap_or_default();
if output.is_empty() { bail!("OpenRouter returned empty review output"); }
// after
let output = parsed.choices.first()
    .and_then(|c| c.message.as_ref())
    .map(|m| m.content.trim().to_string())
    .unwrap_or_default();
let output = if output.is_empty() {
    eprintln!("empty review output; retrying once");
    retry_request(&client, &api_key, &body)?
} else { output };
Defensive patterns

Strategy: retry

Validate before calling

let body = serde_json::to_string(&request)?;
// after the response:
let text = parsed.choices.first()
    .and_then(|c| c.message.as_ref())
    .map(|m| m.content.trim().to_string())
    .unwrap_or_default();
if text.is_empty() { eprintln!("warning: empty model output; will retry"); }

Type guard

fn non_empty_review(resp: &ChatResponse) -> Option<&str> {
    resp.choices.first()
        .and_then(|c| c.message.as_ref())
        .map(|m| m.content.trim())
        .filter(|s| !s.is_empty())
}

Try / catch

match run_review() {
    Err(e) if e.to_string().contains("empty review output") => {
        eprintln!("model returned nothing; retrying with different model");
        run_review_with_fallback_model()?;
    }
    Err(e) => return Err(e),
    Ok(v) => v,
}

Prevention

When it happens

Trigger: Calling the commit review flow when OpenRouter returns a response with an empty choices array, a choice with no message object, or message.content that is whitespace-only (e.g. model produced a refusal or empty completion).

Common situations: Weak or degraded model selected (empty completions), prompt too large so the model returns nothing, provider-side moderation blocking output, malformed/missing API response fields, or a model that outputs only tool-call/refusal content.

Related errors


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