jdx/mise · error

{} {err}

Error message

{} {err}

What it means

On macOS, `mise exec --sandbox` re-execs the command through `sandbox-exec`. This error means the `exec(2)` of that sandbox wrapper itself failed — `Command::exec()` only returns on failure — and the message pairs the sandboxed program path with the OS error (ENOENT for a missing sandbox-exec, EACCES, E2BIG, ...). The intended program never ran; this is the sandbox plumbing failing, not your command.

Source

Thrown at src/cli/exec.rs:411

    };
    if crate::file::is_active_mise_shim(std::path::Path::new(&program)) {
        return Err(eyre::eyre!(
            "recursive shim invocation detected: {}",
            program.to_string_lossy()
        ));
    }
    env::remove_var(env::MISE_SHIM_PATH_ENV);
    // Apply sandbox (Landlock/seccomp on Linux, sandbox-exec on macOS)
    let args_str: Vec<String> = args
        .iter()
        .map(|a| a.to_string_lossy().into_owned())
        .collect();
    if let Some(sandboxed) = sandbox.apply(&program.to_string_lossy(), &args_str).await? {
        // macOS: exec through sandbox-exec
        let err = exec::Command::new(&sandboxed.program)
            .args(&sandboxed.args)
            .exec();
        bail!("{} {err}", sandboxed.program);
    }

    let err = exec::Command::new(program.clone()).args(&args).exec();
    let mut msg = format!("{:?} {err}", program.to_string_lossy());
    // The bin never resolved on PATH. If an installed-but-unconfigured tool
    // would have provided it, say so instead of leaving the user with a bare
    // ENOENT (discussion #4407).
    if resolution_failed && let Some(hint) = crate::shims::exec_resolution_hint(&program_name).await
    {
        msg.push_str("\n\n");
        msg.push_str(&hint);
    }
    bail!("{msg}")
}

/// The opaque `cannot find binary path`, plus an explanation when an
/// installed-but-unconfigured tool would have provided the bin. `mise install`
/// writes to no config file, so its tool dirs never join the PATH `mise exec`

View on GitHub (pinned to 6f52dcdf99)

Solutions

  1. Read the OS error suffix: ENOENT → ensure `/usr/bin/sandbox-exec` exists and is on PATH; EACCES → fix execute permissions; E2BIG → trim env/args
  2. Retry without `--sandbox` to confirm the command and PATH are otherwise fine, then re-enable sandboxing
  3. Remember this branch is macOS-only — on Linux mise uses Landlock/seccomp in-process, so do not chase sandbox-exec there
  4. Inspect the sandboxed.program string printed in the message if the wrapper path itself looks wrong

Example fix

# before
$ mise x --sandbox -- my-tool --flag
Error: /usr/bin/sandbox-exec ... (No such file or directory)

# after
$ mise x -- my-tool --flag   # confirm the binary runs, then fix sandbox-exec availability
Defensive patterns

Strategy: try-catch

Validate before calling

# macOS: confirm sandbox-exec exists before sandboxed runs
command -v sandbox-exec >/dev/null || { echo 'sandbox-exec missing' >&2; exit 2; }

Try / catch

mise x --sandbox -- cmd 2>err.log || { grep -q 'sandbox' err.log && mise x -- cmd; } # fall back to unsandboxed only if policy allows

Prevention

When it happens

Trigger: `mise exec --sandbox -- <cmd>` on macOS where `sandbox.apply()` produced a sandbox-exec invocation but `exec::Command::new(&sandboxed.program).exec()` returns an error: the sandbox-exec binary is absent from PATH, the sandboxed program string points somewhere non-executable, or the accumulated environment/argv exceeds OS limits (E2BIG).

Common situations: Minimal macOS CI images or containers where `/usr/bin/sandbox-exec` is stripped; PATH reordered by mise so the wrapper resolves badly; extremely long argument lists or environments; a sandboxed program path with characters the wrapper mishandles.

Related errors


AI-assisted analysis of jdx/mise@6f52dcdf99 (2026-08-22). Data as JSON: /api/errors/2c978f90b3e4a732. Report an issue: GitHub.