{"record":{"id":"e6a169695f7b510c","repo":"nikivdev/code","slug":"kimi-review-failed","errorCode":null,"errorMessage":"kimi review failed: {}","messagePattern":"kimi review failed: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/commit.rs","lineNumber":6059,"sourceCode":"        }\n        let _ = stderr_tx.send(collected);\n    });\n\n    let status = child.wait().context(\"failed to wait for kimi\")?;\n    let _ = stdout_handle.join();\n    let _ = stderr_handle.join();\n\n    let stdout_bytes = stdout_rx.recv().unwrap_or_default();\n    let stderr_text = stderr_rx.recv().unwrap_or_default();\n\n    if !status.success() {\n        let stdout_text = String::from_utf8_lossy(&stdout_bytes);\n        let error_msg = if stderr_text.trim().is_empty() {\n            stdout_text.trim()\n        } else {\n            stderr_text.trim()\n        };\n        bail!(\"kimi review failed: {}\", error_msg);\n    }\n\n    let stdout_text = String::from_utf8_lossy(&stdout_bytes).trim().to_string();\n    if stdout_text.is_empty() {\n        bail!(\"kimi returned empty output\");\n    }\n\n    // Parse the stream-json output from kimi\n    // Format: {\"role\":\"assistant\",\"content\":[{\"type\":\"think\",\"think\":\"...\"},{\"type\":\"text\",\"text\":\"...\"}]}\n    let result = extract_kimi_text_content(&stdout_text).unwrap_or_else(|| stdout_text.clone());\n    if result.is_empty() {\n        bail!(\"kimi returned empty review output (no text content in response)\");\n    }\n\n    // Try to parse JSON from output\n    let mut review_json = parse_review_json(&result);\n    let future_tasks = review_json\n        .as_ref()","sourceCodeStart":6041,"sourceCodeEnd":6077,"githubUrl":"https://github.com/nikivdev/code/blob/a747e741ae92c09071d0ae946ab48488adcff1ce/src/commit.rs#L6041-L6077","documentation":"Thrown when the kimi CLI subprocess exits with a non-success status. The library picks stderr (or stdout if stderr is empty) as the reason and embeds it in the message, so kimi's own error text is the payload of this error.","triggerScenarios":"kimi process returns non-zero exit; e.g. kimi CLI not installed, API key invalid, quota exceeded, or model/CLI error during review.","commonSituations":"kimi not on PATH or wrong version; missing/expired KIMI API key; quota/billing limits; network failure to Kimi's API; unsupported flags passed by the integration.","solutions":["Read the embedded message for kimi's actual error text and act on it.","Verify kimi is installed and on PATH (`which kimi`, check version).","Re-authenticate kimi / set the API key env variable.","Check quota and billing on the Kimi account.","Retry; transient API failures often resolve."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// preflight: kimi installed and key set\nif which::which(\"kimi\").is_err() { anyhow::bail!(\"kimi CLI not on PATH\"); }\nif std::env::var(\"KIMI_API_KEY\").is_err() { anyhow::bail!(\"KIMI_API_KEY not set\"); }","typeGuard":null,"tryCatchPattern":"match run_kimi_review(&diff).await {\n    Ok(r) => r,\n    Err(e) if e.to_string().starts_with(\"kimi review failed:\") => {\n        let reason = e.to_string().trim_start_matches(\"kimi review failed:\");\n        eprintln!(\"kimi error: {reason}\");\n        fallback_review()\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Verify kimi is on PATH and current before automated runs","Keep the API key env var set in all environments (shell, CI secrets)","Watch quota/billing on the Kimi account","Parse the embedded reason text to distinguish auth vs. quota vs. transient errors"],"tags":["kimi","subprocess","ai-review","exit-code"],"backgroundTag":"ai-cli-nonzero-exit","analyzedSha":"a747e741ae92c09071d0ae946ab48488adcff1ce","analyzedAt":"2026-09-01T22:43:55.719Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}