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

  1. Run `kilo` interactively once and complete login, then retry
  2. Read the stderr excerpt in the message — it carries the CLI's real failure reason (auth vs model vs network)
  3. Verify the binary: `kilo --version`; upgrade it or set KILO_CLI_PATH to a supported release
  4. 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

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

Related errors


AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23). Data as JSON: /api/errors/ffe853cef7dd2c24. Report an issue: GitHub.