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

runtime.shell {shell:?} (resolved to {}) does not exist

Error message

runtime.shell {shell:?} (resolved to {}) does not exist

What it means

After resolution (absolute path taken as-is, bare name found on PATH), validate_shell verifies the resolved target exists. For absolute inputs this is the first real check, so it primarily catches dead absolute paths; for PATH-resolved names it covers the race where the file vanished between lookup and stat.

Source

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

        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()
        ),
    };
    if !metadata.is_file() {
        anyhow::bail!(
            "runtime.shell {shell:?} (resolved to {}) is not a regular file",
            resolved.display()
        );
    }

View on GitHub (pinned to 88bb9c8533)

Solutions

  1. Confirm the path exists (ls it), then point at a shell that is actually present.
  2. Prefer a bare name ("bash") so each machine's PATH picks the right location.
  3. In the docker runtime, ensure the shell is installed in the container image the config targets.
  4. Use /bin/sh as the portable floor when targeting heterogeneous machines.

Example fix

# before
[runtime]
shell = "/usr/bin/fish"   # does not exist on this machine

# after
[runtime]
shell = "bash"   # resolved per-machine via PATH
Defensive patterns

Strategy: validation

Validate before calling

let resolved = if std::path::Path::new(shell).is_absolute() {
    std::path::PathBuf::from(shell)
} else {
    resolve_on_path(shell)? // your own PATH walk
};
if !resolved.exists() { /* point at an installed shell before create_runtime */ }

Try / catch

match create_runtime(&config) {
    Err(e) if e.to_string().contains("does not exist") => {
        // verify with ls / file, switch to a bare name or /bin/sh, retry
    }
    other => other,
}

Prevention

When it happens

Trigger: runtime.shell = "/usr/bin/fish" on a machine without fish; a stale absolute path after the shell was upgraded, moved, or removed; a PATH-found file deleted between resolution and the exists() check.

Common situations: Config copied between machines with different layouts; brew or apt upgrades relocating shells; containers whose runtime image differs from the dev box the config was written on.

Related errors


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