{"record":{"id":"f4e9306e7b66eefd","repo":"jdx/mise","slug":"no-dynamic-linker-found-for-homebrew-bottles","errorCode":null,"errorMessage":"no dynamic linker found for {} — Homebrew bottles require glibc (musl-based distros are unsupported)","messagePattern":"no dynamic linker found for (.+?) — Homebrew bottles require glibc \\(musl-based distros are unsupported\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/system/packages/brew/prefix.rs","lineNumber":115,"sourceCode":"        return Ok(());\n    }\n    if ld.exists() {\n        return Ok(()); // valid symlink or file already in place\n    }\n    if ld.symlink_metadata().is_ok() {\n        crate::file::remove_file(&ld)?; // dangling symlink\n    }\n    let host_loader = [\n        \"/lib64/ld-linux-x86-64.so.2\",\n        \"/lib/ld-linux-aarch64.so.1\",\n        \"/lib64/ld-linux-aarch64.so.1\",\n    ]\n    .iter()\n    .map(Path::new)\n    .find(|p| p.exists())\n    .map(Path::to_path_buf);\n    let Some(target) = host_loader else {\n        bail!(\n            \"no dynamic linker found for {} — Homebrew bottles require glibc (musl-based \\\n             distros are unsupported)\",\n            ld.display()\n        );\n    };\n    crate::file::make_symlink(&target, &ld)?;\n    Ok(())\n}\n\nfn writable(path: &Path) -> bool {\n    // root can write regardless of owner — and `sudo mise` must never treat\n    // a user-owned prefix as broken and chown it to root\n    if nix::unistd::geteuid().is_root() {\n        return path.exists();\n    }\n    !matches!(\n        path.metadata()\n            .map(|m| std::os::unix::fs::MetadataExt::uid(&m)),","sourceCodeStart":97,"sourceCodeEnd":133,"githubUrl":"https://github.com/jdx/mise/blob/afd2eddd3a50c16190efc1c7e94404b48f72af57/src/system/packages/brew/prefix.rs#L97-L133","documentation":"On Linux, Homebrew bottles are built against glibc and need a dynamic loader (ld-linux-*) plus a working loader environment. setup_linux_runtime probes known loader paths; if none exists it bails, because bottle binaries could not run on the host (e.g. a musl-based distro like Alpine).","triggerScenarios":"Installing brew packages on a Linux host where none of the probed glibc loader paths exist — musl-based distros (Alpine), minimal containers without glibc, or a stripped rootfs.","commonSituations":"Using mise's brew bootstrap inside an Alpine Docker image; a minimal CI runner lacking glibc; chroots without ld-linux installed.","solutions":["Use a glibc-based distro (Debian/Ubuntu/RHEL) or a glibc container image","On Alpine, install gcompat or use a non-brew backend for the tools","Pick an alternate backend (aqua, github, cargo) for these packages on musl"],"exampleFix":"# before (Dockerfile)\nFROM alpine:3.20\n# after\nFROM debian:bookworm-slim","handlingStrategy":"fallback","validationCode":"const loader = ['/lib64/ld-linux-x86-64.so.2','/lib/ld-linux-aarch64.so.1'].find(p => fs.existsSync(p));\nif (!loader) console.error('glibc loader missing — brew bottles unsupported here');","typeGuard":"const hasGlibc = () => fs.existsSync('/lib64/ld-linux-x86-64.so.2') || fs.existsSync('/lib/ld-linux-aarch64.so.1');","tryCatchPattern":null,"preventionTips":["Use glibc-based distros/containers for brew backends","On Alpine, plan for gcompat or alternate backends","Document platform requirements in CI image choices"],"tags":["brew","linux","glibc","musl","platform"],"backgroundTag":"unsupported-platform","analyzedSha":"afd2eddd3a50c16190efc1c7e94404b48f72af57","analyzedAt":"2026-09-09T01:38:25.179Z","contentChangedAt":"2026-09-09T01:38:25.179Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}