Hmbown/CodeWhale · error · anyhow::Error

read-only executable path is not valid UTF-8

Error message

read-only executable path is not valid UTF-8

What it means

In hardened read-only shell mode, the command is parsed to argv (hardened_readonly_argv), the program is resolved against the workspace (resolve_readonly_program), and the resulting path is converted with Path::to_str() to build a CommandSpec::program. On Unix, paths are bytes and need not be valid UTF-8; to_str() returns None for such paths, so an executable (or workspace component) containing invalid UTF-8 bytes fails here.

Source

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

        let policy = policy_override.unwrap_or_else(|| self.sandbox_policy.clone());

        // Create command spec and prepare sandboxed environment
        let spec = if let Some(workspace) = readonly_workspace {
            if command.contains('|') {
                // An agent read-only pipeline: every segment was admitted by
                // `is_agent_readonly_shell_command` (no separators, redirects,
                // expansions, or subshells — only `|` between validated
                // segments), so a shell is needed solely to bind the segments
                // and report a failed stage through pipefail.
                let piped = format!("set -o pipefail; {command}");
                CommandSpec::shell(&piped, work_dir.clone(), Duration::from_millis(timeout_ms))
            } else {
                let (program, args) = hardened_readonly_argv(command)?;
                let program = resolve_readonly_program(&program, workspace)?;
                CommandSpec::program(
                    program
                        .to_str()
                        .ok_or_else(|| anyhow!("read-only executable path is not valid UTF-8"))?,
                    args,
                    work_dir.clone(),
                    Duration::from_millis(timeout_ms),
                )
            }
        } else {
            CommandSpec::shell(command, work_dir.clone(), Duration::from_millis(timeout_ms))
        };
        let spec = spec.with_policy(policy).with_env(extra_env);
        let exec_env = self.sandbox_manager.prepare(&spec);

        if background {
            let bounded_output = timeout_bounds_ms == (1, BASH_MAX_TIMEOUT_MS);
            self.spawn_background_sandboxed(
                command,
                &work_dir,
                &exec_env,
                None,

View on GitHub (pinned to 0c42157ee5)

Solutions

  1. Rename or move the executable (or the offending path component) to a valid UTF-8 name.
  2. Run the command outside read-only mode (plain shell mode takes a string command and does not require a UTF-8 program path).
  3. Fix the workspace path if a parent directory carries non-UTF-8 bytes.
Defensive patterns

Strategy: validation

Validate before calling

let program_path = resolve_program(command)?;
anyhow::ensure!(
    program_path.to_str().is_some(),
    "executable path {:?} is not valid UTF-8; rename it or use shell mode",
    program_path
);
exec_readonly(&command)?;

Try / catch

match exec_readonly(&command) {
    Ok(out) => out,
    Err(e) if e.to_string().contains("not valid UTF-8") => {
        // Fall back to plain shell mode, which takes a string command
        exec_shell(&command, None, None).await?
    }
    Err(e) => return Err(e),
};

Prevention

When it happens

Trigger: Running a read-only-mode command whose executable lives at a path with non-UTF-8 bytes (e.g. Latin-1 or otherwise invalid byte sequences in a filename), or where the workspace root itself contains such a component.

Common situations: Filesystems with legacy non-UTF-8 filenames; files created under a different locale; almost never hit on Windows (WTF-16 paths convert) — a Unix-specific edge.

Related errors


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