jdx/mise · error · eyre::Report

remote host '{}' does not provide the dynamic loader require

Error message

remote host '{}' does not provide the dynamic loader required by local mise: {interpreter}; set mise_bin, remote_mise, or bootstrap_command

What it means

Thrown by validate_default_binary_compatibility when uploading the local mise binary to a Linux remote: the PT_INTERP dynamic loader embedded in the local binary (e.g. /lib64/ld-linux-x86-64.so.2) does not exist on the remote (the probe prints MISE_LOADER_MISSING). This almost always means the local and remote libcs differ in kind — a glibc-linked local binary pushed to a musl-only host like Alpine — so the binary could not even start there.

Source

Thrown at src/system/remote.rs:1242

        // A static ELF has no runtime loader or libc compatibility constraint.
        return Ok(());
    };
    let local_output = Command::new(&interpreter).arg("--version").output()?;
    let local_libc = parse_libc_flavor(&combined_output(&local_output)).ok_or_else(|| {
        eyre!(
            "could not identify the libc used by local mise loader {interpreter}; set mise_bin, remote_mise, or bootstrap_command"
        )
    })?;
    let check = format!(
        "if test -x {loader}; then {loader} --version 2>&1 || true; else printf '%s\\n' MISE_LOADER_MISSING; fi",
        loader = shell_quote(&interpreter),
    );
    let remote_output = session.output(&["sh", "-c", &check])?;
    if remote_output
        .lines()
        .any(|line| line == "MISE_LOADER_MISSING")
    {
        bail!(
            "remote host '{}' does not provide the dynamic loader required by local mise: {interpreter}; set mise_bin, remote_mise, or bootstrap_command",
            session.host.name
        );
    }
    let remote_libc = parse_libc_flavor(&remote_output).ok_or_else(|| {
        eyre!(
            "could not identify the libc provided by remote loader {interpreter} on '{}'; set mise_bin, remote_mise, or bootstrap_command",
            session.host.name
        )
    })?;
    if local_libc != remote_libc {
        bail!(
            "remote host '{}' libc {remote_libc:?} is incompatible with local mise libc {local_libc:?}; set mise_bin, remote_mise, or bootstrap_command",
            session.host.name
        );
    }
    let required = match local_libc {
        LibcFlavor::Glibc => max_required_glibc_version(&binary_bytes).ok_or_else(|| {

View on GitHub (pinned to 6f52dcdf99)

Solutions

  1. Let mise download the correct remote artifact instead of uploading the local one: unset mise_bin and set bootstrap_command (e.g. curl https://mise.run | sh) or remote_mise
  2. Point mise_bin at a musl-linked mise binary (mise-v*-linux-{arch}-musl) when targeting Alpine-style remotes
  3. Install a glibc compatibility layer on the remote so the loader path resolves

Example fix

# before (mise.toml)
[bootstrap.remote.hosts.alpine]
host = "root@container"
mise_bin = "~/.local/bin/mise"  # glibc build -> loader missing on Alpine

# after
[bootstrap.remote.hosts.alpine]
host = "root@container"
mise_bin = "~/Downloads/mise-v2026.8.22-linux-x64-musl"  # musl build runs on Alpine
Defensive patterns

Strategy: fallback

Validate before calling

# Pre-flight the loader the local binary needs (from readelf) on the remote:
INTERP=$(readelf -l ./mise | sed -n 's/.*interpreter: \(.*\)]/\1/p')
ssh root@alpine "test -x '$INTERP' && echo loader-ok || echo loader-missing"
# loader-missing -> use a musl mise_bin, or bootstrap_command/remote_mise

Type guard

fn remote_can_run_local_binary(local: &Path, remote_has_loader: bool) -> bool {
    remote_has_loader && {
        let bytes = std::fs::read(local).unwrap_or_default();
        bytes.starts_with(b"\x7fELF")
    }
}

Try / catch

match validate_default_binary_compatibility(&session, &binary, "linux").await {
    Err(e) if e.to_string().contains("does not provide the dynamic loader") => {
        // glibc local vs musl remote: fetch the remote-matched artifact instead
        resolver.resolve(&platform, &binary).await?;
    }
    other => other?,
}

Prevention

When it happens

Trigger: Developing on Ubuntu/Debian/Fedora (glibc) and running remote commands on Alpine/void-musl/NixOS-remote without musl support; any same-arch Linux pair where the remote lacks the loader path the local binary's PT_INTERP names.

Common situations: macOS-like workflows where the workstation distro and the container fleet differ; CI runners on glibc deploying into musl containers; minimal cloud images missing compat loader symlinks.

Related errors


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