Product
BAML
Describe the bug
The published @boundaryml/baml-bridge-linux-x64-musl package contains a glibc-linked .node addon under a musl filename. On a musl host (Alpine) the correct optional dependency is installed and platform detection picks it correctly, but the addon cannot be loaded.
The failure surfaces through napi's fallback message, which is misleading:
Cannot find native binding.
npm has a bug related to optional dependencies ...
That points at npm optional-dependency resolution, which is not what is happening. A direct require() of the addon gives the real error:
Error loading shared library ld-linux-x86-64.so.2: No such file or directory
ld-linux-x86-64.so.2 is the glibc dynamic loader. It does not exist on Alpine.
The ELF headers of the published artifact confirm it:
$ npm pack @boundaryml/baml-bridge-linux-x64-musl@0.15.0
$ tar -xzf boundaryml-baml-bridge-linux-x64-musl-0.15.0.tgz
$ readelf -d package/baml_node.linux-x64-musl.node | grep NEEDED
0x0000000000000001 (NEEDED) Shared library: [libgcc_s.so.1]
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
0x0000000000000001 (NEEDED) Shared library: [ld-linux-x86-64.so.2]
$ readelf -V package/baml_node.linux-x64-musl.node | grep -oE 'GLIBC_[0-9.]+' | sort -uV | tail -3
GLIBC_2.30
GLIBC_2.33
GLIBC_2.34
A genuine musl build links libc.musl-x86-64.so.1 and carries no GLIBC_* versioned symbols.
It is not a copy of the gnu artifact — the two binaries differ, so this looks like the musl build matrix leg compiling against glibc rather than a publish-time file mixup:
musl-named sha256 41d4c751ab78258a756ad29bd77361c4b4fc7b9b5f631c1eb100ad40677da2a9
gnu sha256 a34f464249f6a49036d267f9ae61c97ee93c6ee8d8127b08517e236cae6347a9
Still present on the newest published build. @boundaryml/baml-bridge-linux-x64-musl@0.15.1-nightly.20260809.a has the identical glibc NEEDED set, so there is no version to upgrade to.
Expected
The linux-x64-musl artifact links libc.musl-x86-64.so.1, carries no GLIBC_* versioned symbols, and loads on a stock Alpine image with no compatibility shim.
Actual
A glibc binary published under the musl name. It cannot load on Alpine, and the error message points at npm rather than at the binary.
Workaround
apk add gcompat installs a partial glibc ABI shim providing ld-linux-x86-64.so.2, after which the addon loads. This is not a safe long-term fix: the binary requires symbols up to GLIBC_2.34 (the release that folded libpthread/libdl into libc), and gcompat does not implement all of glibc — it can load successfully and still fail on an unexercised code path. A glibc base image (node:22-slim) avoids the problem entirely.
Suggested fix
Build the musl leg in a musl toolchain (x86_64-unknown-linux-musl with a musl sysroot), and add a release gate that fails if the musl artifact reports any GLIBC_* versioned symbol:
readelf -V "$artifact" | grep -q 'GLIBC_' && { echo "musl artifact is glibc-linked"; exit 1; }
Possibly related
#4279 — baml pack --target *-unknown-linux-musl always fails. Different symptom (packing, not loading), but also musl-target-specific, so the two may share a build-configuration root cause.
Impact
Blocks Alpine-based deployment of any Node service using BAML. Alpine is the default base image for a large share of Node containers, and the misleading npm error costs real debugging time before anyone thinks to check the ELF headers.
Reproduction Steps
On any musl host — node:22-alpine reproduces it:
FROM node:22-alpine
RUN npm install @boundaryml/baml-bridge@0.15.0
RUN node -e "require('@boundaryml/baml-bridge')"
# -> Cannot find native binding. npm has a bug related to optional dependencies...
To see the real cause rather than the napi fallback, require the addon directly:
node -e "require('/app/node_modules/@boundaryml/baml-bridge-linux-x64-musl/baml_node.linux-x64-musl.node')"
# -> Error loading shared library ld-linux-x86-64.so.2: No such file or directory
Platform-independent check — no Alpine needed, the published artifact is enough:
npm pack @boundaryml/baml-bridge-linux-x64-musl@0.15.0
tar -xzf boundaryml-baml-bridge-linux-x64-musl-0.15.0.tgz
readelf -d package/*.node | grep NEEDED # shows libc.so.6, ld-linux-x86-64.so.2
BAML Version
0.15.0 (bridge); also reproduced on 0.15.1-nightly.20260809.a
Language/Framework
Node.js
LLM Provider
Other
LLM Model
n/a — fails at module load, before any LLM call
Operating System
Linux
Browser
Other
Code Editor
VS Code
Product
BAML
Describe the bug
The published
@boundaryml/baml-bridge-linux-x64-muslpackage contains a glibc-linked.nodeaddon under a musl filename. On a musl host (Alpine) the correct optional dependency is installed and platform detection picks it correctly, but the addon cannot be loaded.The failure surfaces through napi's fallback message, which is misleading:
That points at npm optional-dependency resolution, which is not what is happening. A direct
require()of the addon gives the real error:ld-linux-x86-64.so.2is the glibc dynamic loader. It does not exist on Alpine.The ELF headers of the published artifact confirm it:
A genuine musl build links
libc.musl-x86-64.so.1and carries noGLIBC_*versioned symbols.It is not a copy of the gnu artifact — the two binaries differ, so this looks like the musl build matrix leg compiling against glibc rather than a publish-time file mixup:
Still present on the newest published build.
@boundaryml/baml-bridge-linux-x64-musl@0.15.1-nightly.20260809.ahas the identical glibcNEEDEDset, so there is no version to upgrade to.Expected
The
linux-x64-muslartifact linkslibc.musl-x86-64.so.1, carries noGLIBC_*versioned symbols, and loads on a stock Alpine image with no compatibility shim.Actual
A glibc binary published under the musl name. It cannot load on Alpine, and the error message points at npm rather than at the binary.
Workaround
apk add gcompatinstalls a partial glibc ABI shim providingld-linux-x86-64.so.2, after which the addon loads. This is not a safe long-term fix: the binary requires symbols up toGLIBC_2.34(the release that foldedlibpthread/libdlintolibc), and gcompat does not implement all of glibc — it can load successfully and still fail on an unexercised code path. A glibc base image (node:22-slim) avoids the problem entirely.Suggested fix
Build the musl leg in a musl toolchain (
x86_64-unknown-linux-muslwith a musl sysroot), and add a release gate that fails if the musl artifact reports anyGLIBC_*versioned symbol:Possibly related
#4279 —
baml pack --target *-unknown-linux-muslalways fails. Different symptom (packing, not loading), but also musl-target-specific, so the two may share a build-configuration root cause.Impact
Blocks Alpine-based deployment of any Node service using BAML. Alpine is the default base image for a large share of Node containers, and the misleading npm error costs real debugging time before anyone thinks to check the ELF headers.
Reproduction Steps
On any musl host —
node:22-alpinereproduces it:To see the real cause rather than the napi fallback, require the addon directly:
Platform-independent check — no Alpine needed, the published artifact is enough:
BAML Version
0.15.0(bridge); also reproduced on0.15.1-nightly.20260809.aLanguage/Framework
Node.js
LLM Provider
Other
LLM Model
n/a — fails at module load, before any LLM call
Operating System
Linux
Browser
Other
Code Editor
VS Code