Skip to content

[bug] @boundaryml/baml-bridge-linux-x64-musl ships a glibc binary — addon fails to load on Alpine #4355

Description

@tha-hammer

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

#4279baml 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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions