{"record":{"id":"fe2154199b7773b3","repo":"jdx/mise","slug":"remote-host-does-not-provide-the-dynamic-load","errorCode":null,"errorMessage":"remote host '{}' does not provide the dynamic loader required by local mise: {interpreter}; set mise_bin, remote_mise, or bootstrap_command","messagePattern":"remote host '(.+?)' does not provide the dynamic loader required by local mise: (.+?); set mise_bin, remote_mise, or bootstrap_command","errorType":"exception","errorClass":"eyre::Report","httpStatus":null,"severity":"error","filePath":"src/system/remote.rs","lineNumber":1242,"sourceCode":"        // A static ELF has no runtime loader or libc compatibility constraint.\n        return Ok(());\n    };\n    let local_output = Command::new(&interpreter).arg(\"--version\").output()?;\n    let local_libc = parse_libc_flavor(&combined_output(&local_output)).ok_or_else(|| {\n        eyre!(\n            \"could not identify the libc used by local mise loader {interpreter}; set mise_bin, remote_mise, or bootstrap_command\"\n        )\n    })?;\n    let check = format!(\n        \"if test -x {loader}; then {loader} --version 2>&1 || true; else printf '%s\\\\n' MISE_LOADER_MISSING; fi\",\n        loader = shell_quote(&interpreter),\n    );\n    let remote_output = session.output(&[\"sh\", \"-c\", &check])?;\n    if remote_output\n        .lines()\n        .any(|line| line == \"MISE_LOADER_MISSING\")\n    {\n        bail!(\n            \"remote host '{}' does not provide the dynamic loader required by local mise: {interpreter}; set mise_bin, remote_mise, or bootstrap_command\",\n            session.host.name\n        );\n    }\n    let remote_libc = parse_libc_flavor(&remote_output).ok_or_else(|| {\n        eyre!(\n            \"could not identify the libc provided by remote loader {interpreter} on '{}'; set mise_bin, remote_mise, or bootstrap_command\",\n            session.host.name\n        )\n    })?;\n    if local_libc != remote_libc {\n        bail!(\n            \"remote host '{}' libc {remote_libc:?} is incompatible with local mise libc {local_libc:?}; set mise_bin, remote_mise, or bootstrap_command\",\n            session.host.name\n        );\n    }\n    let required = match local_libc {\n        LibcFlavor::Glibc => max_required_glibc_version(&binary_bytes).ok_or_else(|| {","sourceCodeStart":1224,"sourceCodeEnd":1260,"githubUrl":"https://github.com/jdx/mise/blob/6f52dcdf99e282ef7a7db68c81301fa4618d0f79/src/system/remote.rs#L1224-L1260","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["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","Point mise_bin at a musl-linked mise binary (mise-v*-linux-{arch}-musl) when targeting Alpine-style remotes","Install a glibc compatibility layer on the remote so the loader path resolves"],"exampleFix":"# before (mise.toml)\n[bootstrap.remote.hosts.alpine]\nhost = \"root@container\"\nmise_bin = \"~/.local/bin/mise\"  # glibc build -> loader missing on Alpine\n\n# after\n[bootstrap.remote.hosts.alpine]\nhost = \"root@container\"\nmise_bin = \"~/Downloads/mise-v2026.8.22-linux-x64-musl\"  # musl build runs on Alpine","handlingStrategy":"fallback","validationCode":"# Pre-flight the loader the local binary needs (from readelf) on the remote:\nINTERP=$(readelf -l ./mise | sed -n 's/.*interpreter: \\(.*\\)]/\\1/p')\nssh root@alpine \"test -x '$INTERP' && echo loader-ok || echo loader-missing\"\n# loader-missing -> use a musl mise_bin, or bootstrap_command/remote_mise","typeGuard":"fn remote_can_run_local_binary(local: &Path, remote_has_loader: bool) -> bool {\n    remote_has_loader && {\n        let bytes = std::fs::read(local).unwrap_or_default();\n        bytes.starts_with(b\"\\x7fELF\")\n    }\n}","tryCatchPattern":"match validate_default_binary_compatibility(&session, &binary, \"linux\").await {\n    Err(e) if e.to_string().contains(\"does not provide the dynamic loader\") => {\n        // glibc local vs musl remote: fetch the remote-matched artifact instead\n        resolver.resolve(&platform, &binary).await?;\n    }\n    other => other?,\n}","preventionTips":["Match binaries to fleet libc: keep a musl build around for Alpine targets (mise_bin per host)","Prefer bootstrap_command for heterogeneous fleets so each remote self-installs","Document each host's distro in the hosts entry comments to avoid glibc/musl surprises"],"tags":["mise","remote-bootstrap","dynamic-loader","glibc","musl","alpine","elf"],"backgroundTag":"dynamic-loader-missing","analyzedSha":"6f52dcdf99e282ef7a7db68c81301fa4618d0f79","analyzedAt":"2026-08-22T10:14:23.840Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}