Hmbown/CodeWhale · error

no trusted executable search path remains outside the…

Error message

no trusted executable search path remains outside the workspace

What it means

After rejecting path-qualified programs, the resolver filters the process PATH down to entries that are absolute and canonicalize outside the workspace (`readonly_sanitized_path_from`). If no PATH entry survives — every entry is relative, unresolvable, or inside the workspace — this error is thrown because no trusted location exists to resolve the allowlisted executable from.

Solutions

  1. Add a system-wide directory outside the workspace to PATH, e.g. `PATH=/usr/local/bin:/usr/bin:$PATH`
  2. Move the required binary to an installed location (`cargo install`, distro package, /usr/local/bin)
  3. Ensure PATH entries are absolute and point at existing directories outside the workspace

Example fix

// before
PATH=./node_modules/.bin app
// after
PATH=/usr/local/bin:/usr/bin app  # tool installed system-wide
Defensive patterns

Strategy: validation

Validate before calling

fn has_trusted_path_entries(workspace: &std::path::Path) -> bool {
    let Some(path) = std::env::var_os("PATH") else { return false };
    let Ok(workspace) = workspace.canonicalize() else { return false };
    std::env::split_paths(&path).any(|entry| {
        entry.is_absolute()
            && entry.canonicalize().map(|r| !r.starts_with(&workspace)).unwrap_or(false)
    })
}
assert!(has_trusted_path_entries(&workspace), "PATH needs an absolute entry outside the workspace");

Prevention

When it happens

Trigger: Running with `PATH=.` or `PATH=$HOME/project` (the workspace itself); PATH containing only relative entries like `bin`; running with cwd-inside-workspace PATH entries so the filter removes them all; PATH entries that are dangling symlinks or nonexistent directories that fail canonicalize().

Common situations: Vendored-tool setups that prepend the project's `node_modules/.bin` or `target/debug` to PATH as the only entry; sandboxes that rewrite PATH to workspace-relative dirs; broken images where PATH points at removed directories.

Understand the failure class

Background: "environment variable is not set" and "Missing keys in environment" errors: what missing required env var messages mean and how to fix them — this error's family across 28 libraries.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22). Data as JSON: /api/errors/1f453ff41934b3d0. Report an issue: GitHub.

Appendix: source

Thrown at crates/tui/src/tools/shell.rs:4396

fn resolve_readonly_program(program: &str, workspace: &std::path::Path) -> Result<PathBuf> {
    let path = std::env::var_os("PATH")
        .ok_or_else(|| anyhow!("no executable search path is configured"))?;
    resolve_readonly_program_from_path(program, workspace, &path)
}

fn resolve_readonly_program_from_path(
    program: &str,
    workspace: &std::path::Path,
    path: &std::ffi::OsStr,
) -> Result<PathBuf> {
    let workspace = workspace.canonicalize()?;
    if std::path::Path::new(program).components().count() != 1 {
        return Err(anyhow!(
            "read-only command must name a bare allowlisted executable"
        ));
    }
    let safe_path = readonly_sanitized_path_from(&workspace, path).ok_or_else(|| {
        anyhow!("no trusted executable search path remains outside the workspace")
    })?;
    let names = if cfg!(windows) {
        vec![format!("{program}.exe"), format!("{program}.com")]
    } else {
        vec![program.to_string()]
    };
    for directory in std::env::split_paths(&safe_path) {
        for name in &names {
            let candidate = directory.join(name);
            if !candidate.is_file() {
                continue;
            }
            #[cfg(unix)]
            {
                use std::os::unix::fs::PermissionsExt as _;
                if candidate.metadata()?.permissions().mode() & 0o111 == 0 {
                    continue;
                }

View on GitHub (pinned to 73e0f67d83)