nikivdev/code · error

kimi returned empty output

Error message

kimi returned empty output

What it means

Thrown when the kimi process exits successfully but produced no stdout at all. The library treats empty output as unusable (nothing to parse) and bails with this distinct message so it isn't confused with a kimi-reported failure.

Source

Thrown at src/commit.rs:6064

    let _ = stdout_handle.join();
    let _ = stderr_handle.join();

    let stdout_bytes = stdout_rx.recv().unwrap_or_default();
    let stderr_text = stderr_rx.recv().unwrap_or_default();

    if !status.success() {
        let stdout_text = String::from_utf8_lossy(&stdout_bytes);
        let error_msg = if stderr_text.trim().is_empty() {
            stdout_text.trim()
        } else {
            stderr_text.trim()
        };
        bail!("kimi review failed: {}", error_msg);
    }

    let stdout_text = String::from_utf8_lossy(&stdout_bytes).trim().to_string();
    if stdout_text.is_empty() {
        bail!("kimi returned empty output");
    }

    // Parse the stream-json output from kimi
    // Format: {"role":"assistant","content":[{"type":"think","think":"..."},{"type":"text","text":"..."}]}
    let result = extract_kimi_text_content(&stdout_text).unwrap_or_else(|| stdout_text.clone());
    if result.is_empty() {
        bail!("kimi returned empty review output (no text content in response)");
    }

    // Try to parse JSON from output
    let mut review_json = parse_review_json(&result);
    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 {

View on GitHub (pinned to a747e741ae)

Solutions

  1. Run the same kimi command manually with the same flags to see where output actually goes.
  2. Check stderr output from the run for silent warnings.
  3. Update kimi CLI; a stdout/stderr behavior change may be version-related.
  4. Retry the review; if reproducible, report to kimi with the exact prompt/flags.
Defensive patterns

Strategy: fallback

Validate before calling

// after run, before parsing: require usable stdout
let stdout = String::from_utf8_lossy(&output.stdout).trim().to_string();
if stdout.is_empty() {
    anyhow::bail!("kimi produced no stdout; stderr: {}", String::from_utf8_lossy(&output.stderr));
}

Try / catch

match run_kimi_review(&diff).await {
    Err(e) if e.to_string() == "kimi returned empty output" => {
        eprintln!("kimi returned nothing; retrying once...");
        run_kimi_review(&diff).await
    }
    other => other,
}

Prevention

When it happens

Trigger: kimi exits 0 but stdout_bytes trims to empty — e.g. kimi wrote results only to stderr, was silently killed, or produced no completion.

Common situations: Piping/redirect misconfiguration swallowing stdout; kimi CLI printing to stderr while exiting 0; timeouts or signals killing kimi after it started; kimi bug with certain prompts.

Related errors


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