Skip to content

fix(npm): detect musl libc to resolve correct binary on Alpine Linux - #329

Closed
aperkaz wants to merge 1 commit into
JamieMason:mainfrom
aperkaz:main
Closed

aperkaz wants to merge 1 commit into
JamieMason:mainfrom
aperkaz:main

Conversation

@aperkaz

@aperkaz aperkaz commented Apr 16, 2026

Copy link
Copy Markdown
Contributor

Description (What)

Adds musl libc detection to the binary resolution logic in npm/index.cjs. On Linux, the launcher now checks /usr/bin/ldd for the presence of "musl" and appends -musl to the optional dependency name when detected, resolving to syncpack-linux-{arch}-musl instead of the glibc variant.

Justification (Why)

On Alpine Linux and other musl-based distros, syncpack fails at runtime with:

Error relocating /node_modules/syncpack-linux-x64/bin/syncpack: __res_init: symbol not found

The glibc-linked binary is resolved because index.cjs has no way to distinguish musl from glibc — it only considers process.platform and process.arch. The musl binary packages (syncpack-linux-x64-musl, syncpack-linux-arm64-musl) are already built and published but were unreachable.

How Can This Be Tested?

  • Alpine (musl): Run in an Alpine Docker container — node npm/index.cjs should resolve syncpack-linux-x64-musl
docker run --rm -it -v $(pwd):/app -w /app node:alpine node -e \
  "console.log(require('fs').readFileSync('/usr/bin/ldd','utf8').includes('musl'))"
# → true
  • glibc Linux / macOS / Windows: Verify isMusl is false and existing behavior is unchanged
  • Missing /usr/bin/ldd: The try/catch returns false, falling back to the glibc package

On Alpine and other musl-based distros, the glibc binary was resolved
instead of the musl variant, causing: `Error relocating
syncpack-linux-x64/bin/syncpack: __res_init: symbol not found`
@JamieMason

Copy link
Copy Markdown
Owner

Thanks a lot for this @aperkaz,
Since syncpack requires node 14+, we can use process.report.getReport()

function isMusl() {
  try {
    if (process.platform !== 'linux') return false;
    const { sharedObjects } = process.report.getReport()
    return sharedObjects.some((obj) => obj.includes('musl'));
  } catch (_) {
    return false;
  }
}

@JamieMason

Copy link
Copy Markdown
Owner

Thanks a lot for this @aperkaz, this is released in 15.0.0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants