zeroclaw-labs/zeroclaw · error · anyhow::Error

runtime.shell {shell:?} was not found on PATH; use an absolu

Error message

runtime.shell {shell:?} was not found on PATH; use an absolute path or install the shell

What it means

When runtime.shell is a bare name, validate_shell walks PATH and takes the first directory containing a file of that name; if no PATH entry has one it bails. This lookup only checks is_file() — executability of the resolved path is verified by the later checks.

Source

Thrown at crates/zeroclaw-config/src/platform/mod.rs:54

    if shell.trim().is_empty() {
        anyhow::bail!("runtime.shell must not be empty or whitespace");
    }

    let path = std::path::Path::new(shell);
    let resolved = if path.is_absolute() {
        path.to_path_buf()
    } else if path.components().count() > 1 {
        anyhow::bail!(
            "runtime.shell {shell:?} is a relative path; use a bare name resolved on PATH (e.g. \"bash\") or an absolute path (e.g. \"/bin/bash\")"
        );
    } else {
        match std::env::split_paths(&std::env::var_os("PATH").unwrap_or_default())
            .map(|dir| dir.join(shell))
            .find(|candidate| candidate.is_file())
        {
            Some(found) => found,
            None => anyhow::bail!(
                "runtime.shell {shell:?} was not found on PATH; use an absolute path or install the shell"
            ),
        }
    };

    if !resolved.exists() {
        anyhow::bail!(
            "runtime.shell {shell:?} (resolved to {}) does not exist",
            resolved.display()
        );
    }

    let metadata = match resolved.metadata() {
        Ok(metadata) => metadata,
        Err(e) => anyhow::bail!(
            "runtime.shell {shell:?} (resolved to {}) could not be inspected: {e}",
            resolved.display()
        ),

View on GitHub (pinned to 88bb9c8533)

Solutions

  1. Use the absolute path where the shell actually lives (e.g. /opt/homebrew/bin/fish).
  2. Install the shell (apt install fish / brew install fish).
  3. Fix the PATH seen by the process: systemd Environment=PATH=..., docker ENV, or launch from a login shell.
  4. Fall back to a shell that is essentially always present: /bin/sh or /bin/bash.

Example fix

# before
[runtime]
shell = "fish"   # not on PATH

# after
[runtime]
shell = "/opt/homebrew/bin/fish"
Defensive patterns

Strategy: validation

Validate before calling

fn on_path(name: &str) -> Option<std::path::PathBuf> {
    std::env::split_paths(&std::env::var_os("PATH").unwrap_or_default())
        .map(|dir| dir.join(name))
        .find(|c| c.is_file())
}

if shell == bare_name && on_path(shell).is_none() { /* use an absolute path instead */ }

Try / catch

match create_runtime(&config) {
    Err(e) if e.to_string().contains("not found on PATH") => {
        // pin an absolute path (or install the shell / fix PATH) and retry
    }
    other => other,
}

Prevention

When it happens

Trigger: runtime.shell = "fish" (or zsh, nu, ...) with no executable of that name in any PATH entry of the zeroclaw process on unix.

Common situations: Shell installed under a nonstandard prefix not on PATH; zeroclaw launched from systemd, docker, or a GUI launcher with a minimal PATH; the shell simply not installed on the machine.

Related errors


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