Skip to content

fix(npm): install musl binaries on Linux and surface binary crashes#999

Open
bntvllnt wants to merge 1 commit into
railwayapp:masterfrom
bntvllnt:fix/npm-linux-musl-and-crash-reporting
Open

fix(npm): install musl binaries on Linux and surface binary crashes#999
bntvllnt wants to merge 1 commit into
railwayapp:masterfrom
bntvllnt:fix/npm-linux-musl-and-crash-reporting

Conversation

@bntvllnt

@bntvllnt bntvllnt commented Jul 6, 2026

Copy link
Copy Markdown

Fixes #998.

Problem

When installed via npm on some Linux hosts, railway login --browserless (and in fact every network command) exits 1 with no output. The reporter saw a silent failure inside a TTY, which looked like a TTY-detection bug but is actually two stacked defects in the npm distribution channel.

Root cause

1. npm ships the gnu binary on Linux, which can crash.
npm-install/postinstall.js resolves the download target via @napi-rs/triples, whose first Linux entry is the *-unknown-linux-gnu triple. On some Linux hosts that binary hits a general protection fault in vendored crypto during the TLS key exchange, so it dies with SIGSEGV on the first network call:

traps: railway[…] general protection fault … in railway[…]

The musl binary built from the same source works on the same host. This is also why install.sh already prefers musl on Linux:

# use the statically compiled musl bins on linux to avoid linking issues.
linux) platform="unknown-linux-musl" ;;

The gnu-first ordering has two more consequences: npm installs 404 on aarch64 and arm Linux, because only musl assets are published for those architectures.

2. The bin wrapper hides the crash.
bin/railway.js ran the binary and collapsed any failure into exit(1), discarding both the crash signal and the binary's real exit code — turning the segfault into a silent exit 1.

Changes

File Change
npm-install/postinstall.js Resolve Linux targets through an explicit musl map matching the published release assets. Other platforms keep the existing triples lookup.
bin/railway.js Print an actionable message when the binary is killed by a signal, and propagate the binary's real exit code instead of always 1.

Two files, one hunk each. No Rust/binary changes.

Testing

Verified on an affected Linux host by installing this branch as the global package:

  • postinstall now downloads …-x86_64-unknown-linux-musl.tar.gz; the resulting binary is static-pie/musl.
  • railway login --browserless (the exact railway login --browserless exits silently in TTY on Linux #998 repro, in a TTY) now prints the device-code sign-in flow and polls, instead of exiting 1 silently.
  • Exit codes propagate: an unknown subcommand returns 2 (was 1); an unauthenticated whoami returns a clean 1 (was SIGSEGV/139).
  • Wrapper matrix (stub binaries): exit 00, exit 22, SIGSEGV → actionable message + 1.
  • Target map resolves to a published asset for every Linux arch (x64, arm64, ia32, arm); darwin/win32 unchanged.

Notes

  • Suggested release label: release/patch — the fix reaches users through a version bump on npm.
  • A separate follow-up may be worth opening for why the gnu artifact faults (toolchain/CPU baseline), so the gnu build can either be repaired or dropped from the published matrix. This PR removes user impact by not shipping it to npm Linux users, matching install.sh.

The npm postinstall resolved Linux targets via @napi-rs/triples ordering,
which selects the gnu triple. This shipped a binary that can crash
(SIGSEGV during the TLS handshake) on some Linux hosts, 404'd on
aarch64/arm Linux where only musl assets are published, and diverged from
install.sh, which already ships musl to all Linux users to avoid linking
issues.

The bin wrapper also collapsed every failure into a silent exit 1,
discarding both crash signals and the binary's real exit code, which made
that crash unreportable (railwayapp#998).

- npm-install/postinstall.js: resolve Linux targets through an explicit
  musl target map matching the published release assets; other platforms
  keep the existing triples lookup.
- bin/railway.js: print an actionable message when the binary is killed by
  a signal, and propagate the binary's real exit code.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

railway login --browserless exits silently in TTY on Linux

1 participant