Hmbown/CodeWhale · error · std::io::Error

NotFound

NotFound

Error message

{} not found on PATH

What it means

ExternalTool::output()/status() helpers convert a failed tool resolution into NotFound "<type> not found on PATH", where <type> is the full Rust type name from std::any::type_name (e.g. codewhale_tui::dependencies::Git — read the last segment as the tool name). Resolution probes each candidate binary with --version once per process and caches the result, so the error means the probe failed at launch, not merely that Command::spawn would fail.

Source

Thrown at crates/tui/src/dependencies.rs:328

    ///
    /// Callers should chain `.args(...)`, `.current_dir(...)`, and then
    /// call `.output()`, `.status()`, or `.spawn()`.
    fn command() -> Option<Command> {
        let spec = Self::resolve()?;
        let (program, fixed_args) = split_interpreter_spec(&spec);
        let mut cmd = Command::new(&program);
        crate::utils::suppress_console_window(&mut cmd);
        for arg in &fixed_args {
            cmd.arg(arg);
        }
        Some(cmd)
    }

    /// Convenience: run the tool with arguments in a working directory
    /// and return the captured output.
    fn output(args: &[&str], cwd: &std::path::Path) -> std::io::Result<std::process::Output> {
        let mut cmd = Self::command().ok_or_else(|| {
            std::io::Error::new(
                std::io::ErrorKind::NotFound,
                format!("{} not found on PATH", std::any::type_name::<Self>()),
            )
        })?;
        cmd.args(args).current_dir(cwd).output()
    }

    /// Convenience: run the tool with arguments and return only the
    /// exit status (discards stdout/stderr).
    #[allow(dead_code)]
    fn status(args: &[&str], cwd: &std::path::Path) -> std::io::Result<std::process::ExitStatus> {
        let mut cmd = Self::command().ok_or_else(|| {
            std::io::Error::new(
                std::io::ErrorKind::NotFound,
                format!("{} not found on PATH", std::any::type_name::<Self>()),
            )
        })?;
        cmd.args(args).current_dir(cwd).status()

View on GitHub (pinned to 0c42157ee5)

Solutions

  1. Identify the tool from the type name at the end of the message (e.g. ...::dependencies::Gh -> gh) and install it
  2. Verify from the codewhale process's environment, not just your login shell: run <tool> --version the same way codewhale is launched
  3. Add the tool's bin directory to PATH and restart codewhale so the once-per-process resolution cache re-probes
  4. For Python remember the candidate ladder (python3 / py -3): the probe requires a working --version

Example fix

// before
let out = Git::output(&["diff", "--stat"], &repo)?; // NotFound: ...::dependencies::Git not found on PATH

// after: gate the feature on availability
if !Git::available() {
    return Err(anyhow!("git is required; install it and restart codewhale"));
}
let out = Git::output(&["diff", "--stat"], &repo)?;
Defensive patterns

Strategy: validation

Validate before calling

if !Git::available() {
    return Err("git not found: install git and ensure it is on PATH".into());
}
let out = Git::output(&["diff", "--stat"], &repo)?;

Type guard

fn tool_ready<T: ExternalTool>() -> bool {
    T::available()
}

Try / catch

match Git::output(args, cwd) {
    Err(e) if e.kind() == io::ErrorKind::NotFound => {
        // decode the tool from the message's type name; show an install hint, do not retry
    }
    other => other?,
}

Prevention

When it happens

Trigger: Calling ExternalTool::output/status for Git, Gh, python, node, etc. in a process where none of the tool's candidate binaries respond to --version: not installed, not on PATH, or installed but broken (probe fails and resolution returns None).

Common situations: Slim CI/container images without git/gh/python; PATH differing between the interactive shell and the launching process; a tool present but erroring on --version so the probe rejects it; stale per-process cache after installing the tool mid-session.

Understand the failure class

Background: "Not Found" / HTTP 404 Errors: What They Mean and How to Fix Them Across Libraries — this error's family across 6 libraries.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@0c42157ee5 (2026-08-20). Data as JSON: /api/errors/8dbc861b277d0b99. Report an issue: GitHub.