{"record":{"id":"1844f678c41b5c75","repo":"jdx/mise","slug":"msg","errorCode":null,"errorMessage":"{msg}","messagePattern":"\\{msg\\}","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/cli/exec.rs","lineNumber":424,"sourceCode":"    if let Some(sandboxed) = sandbox.apply(&program.to_string_lossy(), &args_str).await? {\n        // macOS: exec through sandbox-exec\n        let err = exec::Command::new(&sandboxed.program)\n            .args(&sandboxed.args)\n            .exec();\n        bail!(\"{} {err}\", sandboxed.program);\n    }\n\n    let err = exec::Command::new(program.clone()).args(&args).exec();\n    let mut msg = format!(\"{:?} {err}\", program.to_string_lossy());\n    // The bin never resolved on PATH. If an installed-but-unconfigured tool\n    // would have provided it, say so instead of leaving the user with a bare\n    // ENOENT (discussion #4407).\n    if resolution_failed && let Some(hint) = crate::shims::exec_resolution_hint(&program_name).await\n    {\n        msg.push_str(\"\\n\\n\");\n        msg.push_str(&hint);\n    }\n    bail!(\"{msg}\")\n}\n\n/// The opaque `cannot find binary path`, plus an explanation when an\n/// installed-but-unconfigured tool would have provided the bin. `mise install`\n/// writes to no config file, so its tool dirs never join the PATH `mise exec`\n/// builds (discussion #4407).\n#[cfg(all(windows, not(test)))]\nasync fn err_cannot_find_binary_path(program_name: &str) -> eyre::Report {\n    let base: eyre::Report = which::Error::CannotFindBinaryPath.into();\n    match crate::shims::exec_resolution_hint(program_name).await {\n        Some(hint) => eyre!(\"{base}\\n\\n{hint}\"),\n        None => base,\n    }\n}\n\n#[cfg(all(windows, not(test)))]\npub async fn exec_program<T, U>(\n    program: T,","sourceCodeStart":406,"sourceCodeEnd":442,"githubUrl":"https://github.com/jdx/mise/blob/9dcfcaa0dc8747a2577d3270b69bb9d8313b2807/src/cli/exec.rs#L406-L442","documentation":"mise exec / mise x tried to replace its own process with the requested program via exec(2) and the OS refused, almost always ENOENT because the binary was not on the PATH mise built for the active toolset. When mise knows an installed-but-unconfigured tool provides that bin, it appends a hint: `mise install` writes to no config file, so its tool dirs never join that PATH (discussion #4407). The raw program path and OS error are printed verbatim.","triggerScenarios":"Running `mise exec -- <bin>` or `mise x -- <bin>` where <bin> resolves on neither the ambient PATH nor the toolset PATH: tool installed via `mise install <tool>` without ever being added to mise.toml/.tool-versions, tool listed in a config that is not loaded in this directory, typo in the command name, or the tool's version was never actually installed.","commonSituations":"CI installs tools with `mise install` but the project config never lists them, so `mise exec -- <bin>` gets a bare ENOENT; running a one-off `mise x -- prettier` on a machine where no config provides prettier; a package upgrade renamed its bin.","solutions":["Add the tool to config so its dirs join the PATH mise exec builds: `mise use <tool>@<version>` (project) or `mise use -g <tool>` (global), then retry","Verify resolution first: `mise which <bin>` — if that errors, the toolset does not provide the bin","If the tool is only installed (not configured), either configure it with `mise use` or accept that `mise install` alone never puts it on mise exec's PATH (#4407)","Check the spelling of the command against `mise ls` output and the tool's docs; some tools install bins under different names","If the bin must come from the ambient shell, extend PATH in config (env._path / [env] PATH in mise.toml) or run it outside `mise exec`"],"exampleFix":"# before\nmise install node@22\nmise exec -- prettier --check .   # fails: prettier never configured, ENOENT\n\n# after\nmise use npm:prettier@3\nmise exec -- prettier --check .","handlingStrategy":"validation","validationCode":"#!/bin/bash\n# fail fast if the toolset cannot provide the bin\nif ! mise which \"$BIN\" >/dev/null 2>&1; then\n  echo \"mise: '$BIN' not provided by toolset; adding it\" >&2\n  mise use \"npm:$BIN\"   # or the backend that ships it\nfi\nmise exec -- \"$BIN\" \"$@\"","typeGuard":null,"tryCatchPattern":"if ! mise exec -- \"$BIN\" \"$@\"; then\n  if ! mise which \"$BIN\" >/dev/null 2>&1; then\n    echo \"config missing for $BIN — run: mise use <backend>:$BIN\" >&2\n  fi\n  exit 1\nfi","preventionTips":["Every tool a script execs must be declared in mise.toml/.tool-versions via `mise use`, not merely installed with `mise install`","Add a CI smoke check after install: `mise which <bin>` for each required command before the real steps run","Run `mise doctor` in onboarding to confirm the toolset resolves the bins you expect","Prefer `mise x -- <backend>:<tool> -- <bin>` for one-off tool runs so the dependency is explicit"],"tags":["mise","exec","enoent","command-not-found","path","toolset"],"backgroundTag":"command-not-found","analyzedSha":"9dcfcaa0dc8747a2577d3270b69bb9d8313b2807","analyzedAt":"2026-08-17T14:28:50.624Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}