tinyhumansai/openhuman · error · anyhow::Error

[claude-code][driver] exit {:?} stderr={}

Error message

[claude-code][driver] exit {:?} stderr={}

What it means

The claude-code CLI child exited with a non-zero exit status. Unlike the agent-sdk path, output may have been streamed, but the process itself failed; the exit code and trimmed stderr are included in the message. This indicates a process-level failure (crash, CLI-side abort) rather than a well-formed in-stream error.

Source

Thrown at src/openhuman/inference/provider/claude_code/driver.rs:486

        Ok(inner) => inner?,
        Err(_elapsed) => {
            log::error!(
                "[claude-code][driver] turn timeout ({TURN_TIMEOUT:?}) exceeded; killing child"
            );
            // kill_on_drop handles cleanup, but explicit kill gives us
            // a chance to collect stderr.
            let _ = child.kill().await;
            anyhow::bail!(
                "[claude-code][driver] turn timed out after {:?}",
                TURN_TIMEOUT
            );
        }
    };

    let stderr_text = stderr_task.await.unwrap_or_default();

    if !status.success() {
        anyhow::bail!(
            "[claude-code][driver] exit {:?} stderr={}",
            status.code(),
            stderr_text.trim()
        );
    }
    if let Some(err) = mapper.error.clone() {
        anyhow::bail!("[claude-code][driver] {}", err);
    }

    Ok(mapper.into_response())
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn write_mcp_http_config_emits_http_url_with_bearer_header() {

View on GitHub (pinned to 7491200858)

Solutions

  1. Match on the `exit {:?}` code and `stderr=` text: exit 2 with usage text usually means an unsupported flag → update the CLI or the core.
  2. Update the claude CLI to the latest version so the driver's flags and the CLI agree.
  3. Run the failing command manually with the same args (visible in the `[claude-code][driver] spawn` debug log) to reproduce.
  4. For OOM/kill exits, reduce concurrent turns or increase available memory.
Defensive patterns

Strategy: try-catch

Try / catch

if let Err(e) = driver.run(ctx).await {
    let s = e.to_string();
    if s.contains("exit") && s.contains("stderr=") {
        // extract stderr for triage; exit 2 + usage text ⇒ flag/version skew ⇒ update CLI
        report_cli_update_needed(s);
    }
    return Err(e);
}

Prevention

When it happens

Trigger: The `claude` CLI exits non-zero during a claude-code turn: startup failure (bad flag/`--print-mode` incompatibility with the installed CLI version), runtime crash, auth failure at boot, or external kill. Fires whenever `!status.success()` after the turn completes within TURN_TIMEOUT.

Common situations: Version skew — the installed CLI removed/renamed a flag the driver passes; broken CLI install after auto-update; invalid API credentials causing the CLI to exit at startup; OS-level kills (OOM).

Related errors


AI-assisted analysis of tinyhumansai/openhuman@7491200858 (2026-08-17). Data as JSON: /api/errors/6858a84dfd712c08. Report an issue: GitHub.