{"record":{"id":"290e080a4e358b7d","repo":"jdx/mise","slug":"remote-host-libc-remote-libc-is-incompati","errorCode":null,"errorMessage":"remote host '{}' libc {remote_libc:?} is incompatible with local mise libc {local_libc:?}; set mise_bin, remote_mise, or bootstrap_command","messagePattern":"remote host '(.+?)' libc (.+?) is incompatible with local mise libc (.+?); set mise_bin, remote_mise, or bootstrap_command","errorType":"exception","errorClass":"eyre::Report","httpStatus":null,"severity":"error","filePath":"src/system/remote.rs","lineNumber":1254,"sourceCode":"    );\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(|| {\n            eyre!(\n                \"could not determine the glibc ABI required by local mise; set mise_bin, remote_mise, or bootstrap_command\"\n            )\n        })?,\n        LibcFlavor::Musl => parse_musl_runtime_version(&combined_output(&local_output))\n            .ok_or_else(|| {\n                eyre!(\n                    \"could not determine the musl version used by local mise loader {interpreter}; set mise_bin, remote_mise, or bootstrap_command\"\n                )\n            })?,\n    };\n    let available = match remote_libc {","sourceCodeStart":1236,"sourceCodeEnd":1272,"githubUrl":"https://github.com/jdx/mise/blob/6f52dcdf99e282ef7a7db68c81301fa4618d0f79/src/system/remote.rs#L1236-L1272","documentation":"Thrown by validate_default_binary_compatibility when the remote DOES have the loader path the local mise binary requests, but running '<loader> --version' on the remote reports a different libc family than the local one (glibc vs musl). It is the flavor-level companion of the loader-missing check: the interpreter exists (often via a compat package) yet the libc it implements differs, so the uploaded binary would crash or misbehave.","triggerScenarios":"Local glibc mise pushed to a remote that ships a musl loader at the glibc path (or vice versa) through a compatibility layer; mixed-libc systems with aliased loader paths.","commonSituations":"Remotes with gcompat/musl-compat packages exposing alien loader paths; hand-symlinked loaders by admins trying to run foreign binaries.","solutions":["Remove the explicit local upload: use bootstrap_command (official install script fetches a remote-matched artifact) or remote_mise","Use mise_bin pointing at a binary linked against the remote's actual libc (musl build for musl hosts)","Drop the compat aliases on the remote so detection is honest, then rely on official artifact download"],"exampleFix":"# before (mise.toml)\n[bootstrap.remote.hosts.edge]\nhost = \"ops@edge\"\nmise_bin = \"./mise-glibc\"  # remote loader at same path is musl via gcompat\n\n# after\n[bootstrap.remote.hosts.edge]\nhost = \"ops@edge\"\nbootstrap_command = \"curl -fsSL https://mise.run | sh\"","handlingStrategy":"fallback","validationCode":"# Compare libc families explicitly before relying on local-binary upload:\nlocal=$(ldd --version | head -1 | tr '[:upper:]' '[:lower:]')\nremote=$(ssh ops@edge 'ldd --version 2>&1 | head -1' | tr '[:upper:]' '[:lower:]')\nfor f in glibc musl; do\n  case \"$local\" in *$f*) case \"$remote\" in *$f*) echo \"family ok: $f\";; *) echo \"family mismatch: use bootstrap_command\";; esac;; esac\ndone","typeGuard":"fn libc_families_match(local_out: &str, remote_out: &str) -> bool {\n    parse_libc_flavor(local_out).is_some_and(|l| parse_libc_flavor(remote_out) == Some(l))\n}","tryCatchPattern":"match validate_default_binary_compatibility(&session, &binary, \"linux\").await {\n    Err(e) if e.to_string().contains(\"libc\") && e.to_string().contains(\"incompatible\") => {\n        resolver.resolve(&platform, &binary).await?; // official remote artifact instead\n    }\n    other => other?,\n}","preventionTips":["Don't rely on compat layers (gcompat) to masquerade loader paths; they confuse detection","Keep per-host mise_bin values aligned with each remote's real libc","Standardize fleet distros where possible to keep one provisioning path"],"tags":["mise","remote-bootstrap","libc","glibc","musl","compatibility"],"backgroundTag":"glibc-musl-mismatch","analyzedSha":"6f52dcdf99e282ef7a7db68c81301fa4618d0f79","analyzedAt":"2026-08-22T10:14:23.840Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}