Skip to content
Latchkey

Node "@swc/core platform binary missing" in CI

@swc/core loads a native binding from a platform-specific package (e.g. @swc/core-linux-x64-gnu). When that optional package is missing, swc fails with "Failed to load native binding".

What this error means

A build or test using swc fails with "Failed to load native binding" or "Cannot find module '@swc/core-linux-x64-gnu'". It runs locally where the matching platform package was installed.

node
Error: Failed to load native binding
    at Object.<anonymous> (/work/repo/node_modules/@swc/core/binding.js:1:1)
Cannot find module '@swc/core-linux-x64-gnu'

Diagnose it: reproduce the CI install locally

Install failures are usually environment drift rather than a broken lockfile: a different package-manager major, a different Node version, or a cache that is being restored from a run with different inputs. Reproduce the CI conditions before changing the lockfile, because regenerating it hides the real cause.

Terminal
# match the runner exactly, then install from a clean slate
node --version && npm --version
rm -rf node_modules
npm ci --foreground-scripts

# if that succeeds locally but fails in CI, the difference is the cache
# or the package-manager version, not your lockfile

Common causes

Optional platform package not installed

The @swc/core-<platform> optional dependency was skipped, so no native binding loads.

libc mismatch (gnu vs musl)

On Alpine, swc needs the -musl variant; the -gnu package present cannot load.

How to fix it

Install optional deps for the right platform

Include optional dependencies so the correct @swc/core-<platform> package installs.

Terminal
npm ci --include=optional

Match the libc variant to the image

On Alpine use a base/runner that pulls the -musl binding, or switch to a glibc image.

  1. Use a glibc image for the -gnu binding, or Alpine for -musl.
  2. Ensure the lockfile records the platform you build on.
  3. Reinstall after changing the base image.

Verify the fix survives a cold cache

A green run immediately after a fix often proves nothing, because it restored a cache written before the change. Force a cold install once to confirm the fix is real.

.github/workflows/ci.yml
# temporarily bust the cache key to prove the fix on a cold runner
- uses: actions/setup-node@v4
  with:
    node-version: 22
    cache: npm
    cache-dependency-path: package-lock.json
# then bump this suffix once, run, and remove it
#   key: ${{ runner.os }}-node-${{ hashFiles('package-lock.json') }}-v2

How to prevent it

  • Keep optional dependencies enabled so platform bindings install.
  • Match the libc variant (gnu/musl) to the base image.
  • Latchkey self-healing managed runners auto-retry transient native-binding download failures and cache platform packages so swc loads cleanly.

Frequently asked questions

What causes Node "@swc/core platform binary missing" in CI?
There are 2 common causes: optional platform package not installed and libc mismatch (gnu vs musl). The @swc/core-<platform> optional dependency was skipped, so no native binding loads.
How do I fix Node "@swc/core platform binary missing" in CI?
There are 2 fixes depending on which cause you have: install optional deps for the right platform and match the libc variant to the image. Work through them in order, since the first is the most common.
What does Node "@swc/core platform binary missing" in CI actually mean?
A build or test using swc fails with "Failed to load native binding" or "Cannot find module '@swc/core-linux-x64-gnu'".
How do I stop Node "@swc/core platform binary missing" in CI happening again?
Keep optional dependencies enabled so platform bindings install. The prevention section lists 3 changes that keep it from recurring.

Related guides

References

Not every red build is your code. Latchkey repairs the ones that are not, on the runner. Start free → 30-day trial · No credit card