Skip to content
Latchkey

How to Install esbuild in CI Without Platform Binary Errors

esbuild ships a prebuilt Go binary per platform through optional dependencies. CI breaks when the installed binary does not match the runner OS or arch.

esbuild has no node-gyp build - it downloads a platform-specific binary (e.g. @esbuild/linux-x64) as an optional dependency. The classic CI failure is a lockfile or node_modules created on one platform being used on another, so the wrong binary is present.

Why it fails in CI

  • You committed node_modules or a lockfile built on macOS/Windows, then ran on Linux - the optional binary is for the wrong platform.
  • Optional dependencies were omitted (npm ci --omit=optional), so no esbuild binary installed at all.
  • Alpine/musl needs @esbuild/linux-x64-musl, not the glibc variant.

Install it reliably

Install fresh on the target platform and keep optional dependencies enabled so esbuild resolves the correct binary. Never copy node_modules across OS or arch.

Terminal
# clean install on the actual runner platform
npm ci

# do NOT omit optional deps - that drops the platform binary
# (avoid: npm ci --omit=optional)

# on Alpine the musl variant resolves automatically with a clean install
# (esbuild detects musl at install time)

Cache & speed

Cache ~/.npm keyed on the lockfile and runner OS so the binary download is reused. If you cache node_modules, include runner.os and arch in the key so a different platform leg never reuses the wrong binary.

.github/workflows/ci.yml
- uses: actions/cache@v4
  with:
    path: ~/.npm
    key: npm-${{ runner.os }}-${{ hashFiles('**/package-lock.json') }}

Common errors

  • Host version "0.x" does not match binary version "0.y" → cross-platform node_modules; reinstall fresh.
  • Cannot find module '@esbuild/linux-x64' → optional deps were omitted; reinstall with optional deps enabled.
  • On Alpine Error: Cannot find module ...musl → use a clean install so the musl binary resolves.

Key takeaways

  • esbuild downloads a platform binary via optional dependencies - keep them enabled.
  • Never copy node_modules across OS/arch; install fresh on the runner.
  • Key any node_modules cache on runner.os + arch to avoid binary mismatch.

Related guides

Run this faster and cheaper on Latchkey managed runners. Start free →