Skip to content

0.38.0: native module builds broken on Node 20 — pnpm-via-Mise switch pulls in a node-gyp that requires Node ≥22 #727

Open

Description

@SamBarFu

Our last successful deploy was 2026-08-25 16:52 CST, on the same commit that's failing now - checked the diff and nothing changed in package.json/lockfile/.nvmrc between then and today. The only thing that changed in between is the builder went from 0.37.1 to 0.38.0. Now the build on Railway is giving me this error:

prepare railpack-v0.38.0
2s
                   
╭─────────────────╮
│ Railpack 0.38.0 │
╰─────────────────╯

  ↳ Detected Node
  ↳ Using pnpm package manager
  ↳ Found workspace with 6 packages
  ↳ Custom start command detected, skipping Caddy start
            
  Packages  
  ──────────
  pnpm  │  9.0.0    │  idiomatic-version-file (9.0.0)
  node  │  20.20.2  │  idiomatic-version-file (20.20.2)
            
  Steps     
  ──────────
  ▸ install
    $ pnpm add -g node-gyp
    $ pnpm install --frozen-lockfile --prefer-offline
         
  ▸ build
    $ pnpm turbo run build --filter=api
            
  Deploy    
  ──────────
    $ pnpm --filter api start


load build definition from ./railpack-plan.json
1ms

install apt packages: libatomic1
6s
Processing triggers for libc-bin (2.41-12+deb13u3) ...

copy .nvmrc
462ms

install mise packages: node, pnpm
5s
mise node@20.20.2 ✓ installed

copy / /app
608ms

mkdir -p /app/node_modules/.cache
787ms

copy /mise/shims cached
0ms

copy /mise/installs
1s

pnpm add -g node-gyp
3s
Progress: resolved 1, reused 0, downloaded 0, added 0
Progress: resolved 17, reused 0, downloaded 8, added 0
Packages: +20
++++++++++++++++++++
Progress: resolved 20, reused 0, downloaded 20, added 20, done

/opt/pnpm/global/5:
+ node-gyp 13.0.2

Done in 2.3s

copy /usr/local/bin/mise, /etc/mise/config.toml, /root/.local/state/mise
1s

pnpm install --frozen-lockfile --prefer-offline
10s
Scope: all 7 workspace projects
Lockfile is up to date, resolution step is skipped
Progress: resolved 1, reused 0, downloaded 0, added 0
Packages: +619
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Progress: resolved 619, reused 5, downloaded 10, added 13
Progress: resolved 619, reused 5, downloaded 101, added 104
Progress: resolved 619, reused 5, downloaded 268, added 267
Progress: resolved 619, reused 5, downloaded 420, added 409
Progress: resolved 619, reused 5, downloaded 593, added 580
Progress: resolved 619, reused 5, downloaded 612, added 610
Progress: resolved 619, reused 5, downloaded 612, added 613
Progress: resolved 619, reused 5, downloaded 612, added 619, done
.../node_modules/@prisma/client postinstall$ node scripts/postinstall.js
.../node_modules/better-sqlite3 install$ prebuild-install || node-gyp rebuild --release
.../esbuild@0.25.12/node_modules/esbuild postinstall$ node install.js
.../esbuild@0.28.1/node_modules/esbuild postinstall$ node install.js
.../esbuild@0.18.20/node_modules/esbuild postinstall$ node install.js
.../node_modules/@prisma/client postinstall: warning In order to use "@prisma/client", please install Prisma CLI. You can install it with "npm add -D prisma".
.../node_modules/@prisma/client postinstall: Done
.../node_modules/better-sqlite3 install: prebuild-install warn install No prebuilt binaries found (target=20.20.2 runtime=node arch=x64 libc= platform=linux)
.../node_modules/better-sqlite3 install: gyp info it worked if it ends with ok
.../node_modules/better-sqlite3 install: gyp info using node-gyp@13.0.2
.../node_modules/better-sqlite3 install: gyp info using node@20.20.2 | linux | x64
.../esbuild@0.28.1/node_modules/esbuild postinstall: Done
.../esbuild@0.25.12/node_modules/esbuild postinstall: Done
.../node_modules/better-sqlite3 install: gyp info find Python using Python version 3.13.5 found at "/usr/bin/python3"
.../esbuild@0.18.20/node_modules/esbuild postinstall: Done
.../sharp@0.34.5/node_modules/sharp install$ node install/check.js || npm run build
.../node_modules/better-sqlite3 install: gyp ERR! configure error 
.../node_modules/better-sqlite3 install: gyp ERR! stack TypeError: webidl.util.markAsUncloneable is not a function
.../node_modules/better-sqlite3 install: gyp ERR! stack at new CacheStorage (/opt/pnpm/global/5/.pnpm/undici@8.10.0/node_modules/undici/lib/web/cache/cachestorage.js:20:17)
.../node_modules/better-sqlite3 install: gyp ERR! stack at Object.<anonymous> (/opt/pnpm/global/5/.pnpm/undici@8.10.0/node_modules/undici/index.js:179:25)
.../node_modules/better-sqlite3 install: gyp ERR! stack at Module._compile (node:internal/modules/cjs/loader:1521:14)
.../node_modules/better-sqlite3 install: gyp ERR! stack at Module._extensions..js (node:internal/modules/cjs/loader:1623:10)
.../node_modules/better-sqlite3 install: gyp ERR! stack at Module.load (node:internal/modules/cjs/loader:1266:32)
.../node_modules/better-sqlite3 install: gyp ERR! stack at Module._load (node:internal/modules/cjs/loader:1091:12)
.../node_modules/better-sqlite3 install: gyp ERR! stack at Module.require (node:internal/modules/cjs/loader:1289:19)
.../node_modules/better-sqlite3 install: gyp ERR! stack at require (node:internal/modules/helpers:182:18)
.../node_modules/better-sqlite3 install: gyp ERR! stack at Object.<anonymous> (/opt/pnpm/global/5/.pnpm/node-gyp@13.0.2/node_modules/node-gyp/lib/download.js:2:57)
.../node_modules/better-sqlite3 install: gyp ERR! stack at Module._compile (node:internal/modules/cjs/loader:1521:14)
.../node_modules/better-sqlite3 install: gyp ERR! System Linux 6.13.9-railway
.../node_modules/better-sqlite3 install: gyp ERR! command "/mise/installs/node/20.20.2/bin/node" "/opt/pnpm/global/5/node_modules/node-gyp/bin/node-gyp.js" "rebuild" "--release"
.../node_modules/better-sqlite3 install: gyp ERR! cwd /app/node_modules/.pnpm/better-sqlite3@12.11.1/node_modules/better-sqlite3
.../node_modules/better-sqlite3 install: gyp ERR! node -v v20.20.2
.../node_modules/better-sqlite3 install: gyp ERR! node-gyp -v v13.0.2
.../node_modules/better-sqlite3 install: gyp ERR! $npm_package_name better-sqlite3
.../node_modules/better-sqlite3 install: gyp ERR! $npm_package_version 12.11.1
.../node_modules/better-sqlite3 install: gyp ERR! not ok 
.../node_modules/better-sqlite3 install: Failed
 ELIFECYCLE  Command failed with exit code 1.
.../sharp@0.34.5/node_modules/sharp install: Done
Build Failed: build daemon returned an error < failed to solve: process "pnpm install --frozen-lockfile --prefer-offline" did not complete successfully: exit code: 1 >

We're on Node 20.20.2 (pinned via .nvmrc, engines: ">=20"), pnpm 9.0.0 via packageManager.
better-sqlite3 isn't even something we use directly, it's just an unused optional peer of
drizzle-orm/better-auth (we're on postgres). So this only shows up because something in the
image is trying to compile a native module, and that's enough to break the whole build now.

Dug into it a bit and it looks like it's not really a node-gyp bug on its own, it's this combo:

  • your changelog for 0.38.0 says pnpm now installs via Mise instead of Corepack
  • that seems to change where/how pnpm resolves its global tool store, and it picked up a newer
    node-gyp
  • that node-gyp bundles undici 8.10.0 now (used to be 6.26.0-ish), and undici 8.0.3+ has a bug
    where it calls webidl.util.markAsUncloneable when it sets up CacheStorage - that's a Node
    internal that only exists on newer Node builds (added in worker: add markAsUncloneable api nodejs/node#55234), not on 20.x
  • so node-gyp's own download.js (fetching node headers) just dies before it even gets to
    compiling anything
  • node-gyp's engines field now literally says node ^22.22.2 || ^24.15.0 || >=26.0.0, so it's
    not really compatible with Node 20 anymore even though 20 is still an LTS

Also noticed prebuild-install fails first with an empty libc= field
(target=20.20.2 runtime=node arch=x64 libc= platform=linux) before falling back to node-gyp,
not sure if that's related or a separate thing in the 0.38.0 image.

End result: any project pinned to Node 20 that has any native dep anywhere in the tree (even
an unused optional peer that happens to resolve) is going to hit this after upgrading to
0.38.0, with zero changes on their end.

For us the workaround was easy since we don't actually need better-sqlite3:

"pnpm": {
"neverBuiltDependencies": ["better-sqlite3"]
}

but that's not going to help anyone who actually needs to compile something native on Node 20
under 0.38.0.

Activity

  1. iloveitaly commented on Aug 27, 2026

    @iloveitaly
    Collaborator

    Thanks for the detailed report! I'll work on fixing this up (hopefully by EOW the latest!).

    In the meantime, you should be able to use the older version of railpack to fix the issue.

  2. ciscoheat commented on Oct 6, 2026

    @ciscoheat

    I tried it on 0.39.0 but got a similar error, has this been fixed in a later version?

    Edit: Works on 0.37.1, but it would be nice to use the latest version of course. :)

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions