Hmbown/CodeWhale · error

read-only executable path is not valid UTF-8

Error message

read-only executable path is not valid UTF-8

What it means

When a command runs under the hardened read-only policy, the resolved executable path (a PathBuf/OsStr) must be convertible to valid UTF-8 to be passed as a string program name into CommandSpec. If the resolved path contains non-UTF-8 bytes (e.g. unusual bytes in a directory name), the code refuses with this error rather than silently mis-handling the path.

Solutions

  1. Rename the executable and/or its parent directories to use valid UTF-8 names.
  2. Install or reference the binary via a UTF-8-safe path (e.g. symlink it into /usr/local/bin or another ASCII path).
  3. Check PATH and workspace root for non-UTF-8 components and fix the environment; on Unix you can inspect bytes with `path.as_os_str().as_bytes()`.

Example fix

// before
PATH=/home/user/biné:/usr/bin  # non-UTF-8 dir in PATH resolves tool from bad path

// after
ln -s /opt/tools/bin/mytool /usr/local/bin/mytool
# then invoke via the UTF-8-safe /usr/local/bin/mytool
Defensive patterns

Strategy: validation

Validate before calling

// check the resolved program is UTF-8 before running the read-only command
let program = resolve_readonly_program(&program, workspace)?;
if program.to_str().is_none() {
    return Err(anyhow!(
        "executable path {:?} contains non-UTF-8 bytes; rename or symlink it",
        program
    ));
}

Try / catch

// catch and guide the user to fix the environment
match run_readonly(command) {
    Err(e) if e.to_string().contains("not valid UTF-8") => {
        eprintln!("Binary path has non-UTF-8 characters; symlink it to a UTF-8-safe path.");
    }
    other => other?,
}

Prevention

When it happens

Trigger: Running a read-only sandboxed command whose resolved program path — after resolve_readonly_program against the workspace — contains non-UTF-8 bytes, e.g. a binary installed under a directory with Latin-1/invalid-UTF-8 characters in its name.

Common situations: PATH pointing at a directory with non-UTF-8 characters; a workspace path created by a tool that wrote raw bytes into filenames; filesystems that permit non-UTF-8 names (common on Linux).

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


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

Appendix: source

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

        validate_shell_working_dir(&work_dir, working_dir.is_none())?;

        let timeout_ms = timeout_ms.clamp(timeout_bounds_ms.0, timeout_bounds_ms.1);

        // Use override policy if provided, otherwise use the manager's policy
        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('|') {
                let piped = hardened_readonly_pipeline(command, workspace)?;
                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 matches!(spec.sandbox_policy, ExecutionSandboxPolicy::ReadOnly)
            && readonly_workspace.is_none()
        {
            // Arbitrary code with a read-only policy needs kernel enforcement;
            // only the separately hardened argv subset may run without it.
            require_native_readonly_execution(&exec_env)?;
        }

View on GitHub (pinned to 73e0f67d83)