{"record":{"id":"ffe853cef7dd2c24","repo":"zeroclaw-labs/zeroclaw","slug":"kilocli-exited-with-non-zero-status-code-check","errorCode":null,"errorMessage":"KiloCLI exited with non-zero status {code}. Check that KiloCLI is authenticated and the CLI is supported.{stderr_note}","messagePattern":"KiloCLI exited with non-zero status (.+?)\\. Check that KiloCLI is authenticated and the CLI is supported\\.(.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/zeroclaw-providers/src/kilocli.rs","lineNumber":219,"sourceCode":"                        .with_outcome(::zeroclaw_log::EventOutcome::Failure)\n                        .with_attrs(::serde_json::json!({\n                            \"phase\": \"process_wait\",\n                            \"error\": format!(\"{}\", err),\n                        })),\n                    \"kilocli: process wait failed\"\n                );\n                anyhow::Error::msg(format!(\"KiloCLI process failed: {err}\"))\n            })?;\n\n        if !output.status.success() {\n            let code = output.status.code().unwrap_or(-1);\n            let stderr_excerpt = Self::redact_stderr(&output.stderr);\n            let stderr_note = if stderr_excerpt.is_empty() {\n                String::new()\n            } else {\n                format!(\" Stderr: {stderr_excerpt}\")\n            };\n            anyhow::bail!(\n                \"KiloCLI exited with non-zero status {code}. \\\n                 Check that KiloCLI is authenticated and the CLI is supported.{stderr_note}\"\n            );\n        }\n\n        let text = String::from_utf8(output.stdout).map_err(|err| {\n            ::zeroclaw_log::record!(\n                ERROR,\n                ::zeroclaw_log::Event::new(module_path!(), ::zeroclaw_log::Action::Fail)\n                    .with_outcome(::zeroclaw_log::EventOutcome::Failure)\n                    .with_attrs(::serde_json::json!({\n                        \"phase\": \"utf8_decode\",\n                        \"error\": format!(\"{}\", err),\n                    })),\n                \"kilocli: non-UTF-8 stdout\"\n            );\n            anyhow::Error::msg(format!(\"KiloCLI produced non-UTF-8 output: {err}\"))\n        })?;","sourceCodeStart":201,"sourceCodeEnd":237,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-providers/src/kilocli.rs#L201-L237","documentation":"invoke_cli spawns the `kilo` binary (`kilo --print [-m model] -`), writes the prompt to stdin, and waits up to 120 s (KILO_CLI_REQUEST_TIMEOUT). When the process exits non-zero, ZeroClaw reports the exit code plus a truncated stderr excerpt so the CLI's own diagnostics reach the caller. The message names the two dominant causes: an unauthenticated session and an unsupported CLI version.","triggerScenarios":"chat_with_system on KiloCliModelProvider when the `kilo` process exits non-zero: never-completed or expired login, a kilo release that lacks the `--print` mode, an unknown model passed via --model, upstream service outage, or a proxy blocking egress.","commonSituations":"Fresh machine or CI container with kilo installed but no cached credentials; kilo auto-update changing flags; KILO_CLI_PATH pointing at an old binary; corporate proxy silently breaking the CLI's network calls.","solutions":["Run `kilo` interactively once and complete login, then retry","Read the stderr excerpt in the message — it carries the CLI's real failure reason (auth vs model vs network)","Verify the binary: `kilo --version`; upgrade it or set KILO_CLI_PATH to a supported release","If a custom model was passed, confirm it is available to kilo and drop or fix the --model value"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"async fn kilo_ready(binary: &str) -> bool {\n    tokio::process::Command::new(binary)\n        .arg(\"--version\")\n        .output()\n        .await\n        .map(|o| o.status.success())\n        .unwrap_or(false)\n}","typeGuard":null,"tryCatchPattern":"match kilo.chat(req, model, temp).await {\n    Ok(text) => Ok(text),\n    Err(e) => {\n        let msg = e.to_string();\n        if msg.starts_with(\"KiloCLI exited with non-zero status\") {\n            // parse code + stderr excerpt: auth failures need re-login,\n            // network blips may be retried once\n            if msg.contains(\"auth\") || msg.contains(\"login\") {\n                return Err(e.context(\"kilo requires interactive login\"));\n            }\n            kilo.chat(req, model, temp).await\n        } else { Err(e) }\n    }\n}","preventionTips":["Complete `kilo` login on every host and CI image before enabling the provider","Pin a known-good binary via KILO_CLI_PATH and re-verify after kilo updates","Treat auth-flavoured stderr as a re-login signal, not a retry candidate","Keep prompts within the 120 s CLI timeout budget"],"tags":["kilocli","cli","process-exit","authentication","stderr"],"backgroundTag":"cli-non-zero-exit","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}