zeroclaw-labs/zeroclaw · error · anyhow::Error
KiloCLI exited with non-zero status {code}. Check that KiloC
Error message
KiloCLI exited with non-zero status {code}. Check that KiloCLI is authenticated and the CLI is supported.{stderr_note} What it means
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.
Source
Thrown at crates/zeroclaw-providers/src/kilocli.rs:219
.with_outcome(::zeroclaw_log::EventOutcome::Failure)
.with_attrs(::serde_json::json!({
"phase": "process_wait",
"error": format!("{}", err),
})),
"kilocli: process wait failed"
);
anyhow::Error::msg(format!("KiloCLI process failed: {err}"))
})?;
if !output.status.success() {
let code = output.status.code().unwrap_or(-1);
let stderr_excerpt = Self::redact_stderr(&output.stderr);
let stderr_note = if stderr_excerpt.is_empty() {
String::new()
} else {
format!(" Stderr: {stderr_excerpt}")
};
anyhow::bail!(
"KiloCLI exited with non-zero status {code}. \
Check that KiloCLI is authenticated and the CLI is supported.{stderr_note}"
);
}
let text = String::from_utf8(output.stdout).map_err(|err| {
::zeroclaw_log::record!(
ERROR,
::zeroclaw_log::Event::new(module_path!(), ::zeroclaw_log::Action::Fail)
.with_outcome(::zeroclaw_log::EventOutcome::Failure)
.with_attrs(::serde_json::json!({
"phase": "utf8_decode",
"error": format!("{}", err),
})),
"kilocli: non-UTF-8 stdout"
);
anyhow::Error::msg(format!("KiloCLI produced non-UTF-8 output: {err}"))
})?;View on GitHub (pinned to 88bb9c8533)
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
Defensive patterns
Strategy: try-catch
Validate before calling
async fn kilo_ready(binary: &str) -> bool {
tokio::process::Command::new(binary)
.arg("--version")
.output()
.await
.map(|o| o.status.success())
.unwrap_or(false)
} Try / catch
match kilo.chat(req, model, temp).await {
Ok(text) => Ok(text),
Err(e) => {
let msg = e.to_string();
if msg.starts_with("KiloCLI exited with non-zero status") {
// parse code + stderr excerpt: auth failures need re-login,
// network blips may be retried once
if msg.contains("auth") || msg.contains("login") {
return Err(e.context("kilo requires interactive login"));
}
kilo.chat(req, model, temp).await
} else { Err(e) }
}
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- Gemini CLI exited with non-zero status {code}. Check that Ge
- webhook-audit: {e}
- unsupported room visibility '{other}': expected private or p
- channel '{}' does not support forge API requests
- createSession failed ({status}): {body}
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/ffe853cef7dd2c24.
Report an issue: GitHub.