jdx/mise · error
no dynamic linker found for
Error message
no dynamic linker found for {ld} — Homebrew bottles require glibc (musl-based distros are unsupported) What it means
On Linux, Homebrew bottles are glibc-linked and mise's prefix setup must provide a dynamic linker (ld.so) inside the brew prefix. setup_linux_runtime searches for a host glibc loader at the standard paths (/lib64/ld-linux-x86-64.so.2, /lib/ld-linux-aarch64.so.1, etc.) and bails when none exists, since musl-based distros (Alpine, musl Void) cannot run glibc bottles without a brewed glibc.
Solutions
- Install glibc on the host (e.g. Alpine's `apk add glibc` via the gcompat/glibc packages or use a glibc-based base image like debian/ubuntu)
- Let mise brew a glibc keg first so the loader can be taken from Cellar/glibc (ensure the glibc formula can be installed)
- Use a non-brew backend for packages on musl systems (apk-compatible tools, or github:/cargo: backends)
Example fix
// Dockerfile before FROM alpine:3.20 // after FROM debian:bookworm-slim # or apk add --allow-untrusted glibc on alpine
Defensive patterns
Strategy: validation
Validate before calling
[ -x /lib64/ld-linux-x86-64.so.2 ] || [ -x /lib/ld-linux-aarch64.so.1 ] \ || echo "no glibc loader — brew bottles unsupported on this (musl?) system"
Prevention
- Use glibc-based base images (debian, ubuntu) when enabling the brew backend in containers
- On Alpine, install glibc before using brew packages, or avoid the brew backend entirely
- Detect musl early (`ldd --version | grep -q musl`) and pick alternative backends
When it happens
Trigger: Running brew package installation on Linux where no host glibc dynamic linker exists at the checked paths — typically a musl-based distribution (Alpine Linux) or a heavily stripped container without glibc and no brewed glibc keg.
Common situations: Alpine/musl containers or CI images; distroless golang/alpine base images where someone enabled the brew backend; minimal chroots lacking /lib64.
Understand the failure class
Background: "unsupported platform" / "not supported on this platform" errors: what they mean and how to fix them — this error's family across 47 libraries.
Related errors
- no dynamic linker found for
- brew-cask: : only font-only casks without lifecycle hooks…
- cannot relocate : rpath must grow but the dynamic string…
- precompiled erlang is not supported on musl linux
- remote host ' ' libc is incompatible with local mise libc …
AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17).
Data as JSON: /api/errors/1212cc26b354cdd5.
Report an issue: GitHub.
Appendix: source
Thrown at src/system/packages/brew/prefix.rs:115
return Ok(());
}
if ld.exists() {
return Ok(()); // valid symlink or file already in place
}
if ld.symlink_metadata().is_ok() {
crate::file::remove_file(&ld)?; // dangling symlink
}
let host_loader = [
"/lib64/ld-linux-x86-64.so.2",
"/lib/ld-linux-aarch64.so.1",
"/lib64/ld-linux-aarch64.so.1",
]
.iter()
.map(Path::new)
.find(|p| p.exists())
.map(Path::to_path_buf);
let Some(target) = host_loader else {
bail!(
"no dynamic linker found for {} — Homebrew bottles require glibc (musl-based \
distros are unsupported)",
ld.display()
);
};
crate::file::make_symlink(&target, &ld)?;
Ok(())
}
fn writable(path: &Path) -> bool {
// root can write regardless of owner — and `sudo mise` must never treat
// a user-owned prefix as broken and chown it to root
if nix::unistd::geteuid().is_root() {
return path.exists();
}
!matches!(
path.metadata()
.map(|m| std::os::unix::fs::MetadataExt::uid(&m)),View on GitHub (pinned to 533346cc37)