jdx/mise · error
mise executable not found after bootstrap_command
Error message
mise executable not found after bootstrap_command
What it means
After running the user-configured bootstrap_command on a remote host, mise re-scans for mise executables and tries to identify which binary the bootstrap produced. If the post-bootstrap candidate list is completely empty, no mise executable exists anywhere it looks, and it throws this error.
Solutions
- Fix bootstrap_command so it installs mise into a scanned location (PATH, ~/.local/bin, /usr/local/bin, etc.)
- Set remote_mise or mise_bin explicitly to the installed path so no post-bootstrap selection is needed
- Run the bootstrap command manually over SSH to see why it produced no binary
- Check that the remote user's PATH and HOME match the environment discovery scans
Example fix
// before
remote_config.bootstrap_command("curl https://mise.jdx.dev/install.sh | sh")
// after (deterministic install path)
remote_config.bootstrap_command("curl https://mise.jdx.dev/install.sh | MISE_INSTALL_PATH=/usr/local/bin/mise sh")
.mise_bin("/usr/local/bin/mise") Defensive patterns
Strategy: validation
Validate before calling
test -x "$MISE_BIN" || which mise || echo 'no mise found' # run over SSH before bootstrap
Type guard
fn bootstrap_yielded_mise(after: &[String]) -> bool { !after.is_empty() } Try / catch
if let Err(e) = res { if e.to_string().contains("not found after bootstrap_command") { log_bootstrap_output(); fix_bootstrap(); } } Prevention
- Install mise into a standard scanned location (~/.local/bin, /usr/local/bin, ~/.cargo/bin)
- Have bootstrap_command fail loudly (set -e) so silent install failures surface
- Pin the install path with MISE_INSTALL_PATH and set mise_bin to match
- Verify remote PATH and HOME are what you expect before bootstrapping
When it happens
Trigger: Running a remote operation that invokes bootstrap_command when the command failed silently, installed mise to a non-standard path not in PATH or the well-known locations, or the remote user's PATH/HOME differs from what discovery scans.
Common situations: bootstrap_command that installs mise for a different user or into a custom prefix; remote login shell rc files that change PATH; bootstrap script failing without propagating its exit code; misconfigured HOME on the remote host.
Understand the failure class
Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.
Related errors
- bootstrap_command left multiple
- bootstrap_command left multiple unchanged mise executables…
- remote bootstrap failed on
- a provided source resolves to a path
- a validated copy_link has a staged parent
AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17).
Data as JSON: /api/errors/28b6bfd3f2d023fb.
Report an issue: GitHub.
Appendix: source
Thrown at src/system/remote.rs:1414
.get(*candidate)
.and_then(Option::as_ref)
.and_then(|identity| identity.version.split_whitespace().next())
.is_some_and(|version| {
version == env!("CARGO_PKG_VERSION")
|| version == concat!(env!("CARGO_PKG_VERSION"), "-DEBUG")
})
})
.collect::<Vec<_>>();
if let Some(candidate) =
select_unique_remote_mise_candidate(version_candidates, "version-matching")?
{
return Ok(candidate);
}
if let [candidate] = after {
return Ok(candidate.clone());
}
if after.is_empty() {
bail!("mise executable not found after bootstrap_command");
}
bail!(
"bootstrap_command left multiple unchanged mise executables and the installed path is ambiguous: {}; set remote_mise or mise_bin explicitly",
after.join(", ")
)
}
fn select_unique_remote_mise_candidate(
candidates: Vec<&String>,
kind: &str,
) -> Result<Option<String>> {
match candidates.as_slice() {
[] => Ok(None),
[candidate] => Ok(Some((*candidate).clone())),
_ => bail!(
"bootstrap_command left multiple {kind} mise executables and the installed path is ambiguous: {}; set remote_mise or mise_bin explicitly",
candidates
.iter()View on GitHub (pinned to 533346cc37)