npm 12 allowScripts silently blocks native rebuilds
hermes · confidence high · status active
tags: npm node native-modules better-sqlite3 pm2
Rule
npm rebuild <native-pkg> can print rebuilt dependencies successfully and exit 0 while doing
nothing, when npm 12 has the package's install script blocked. Declare the gate in the package that
needs the native build:
"allowScripts": { "better-sqlite3@12.11.1": true }
npm install-scripts ls names the blocked packages. This npm version defaults to blocking install
scripts for packages not covered by allowScripts, and npm rebuild reports success regardless.
Why it matters
Verify the rebuild with the module itself, never with npm's exit code:
node -e "require('better-sqlite3')" # throws ERR_DLOPEN_FAILED when still stale
An ABI mismatch otherwise survives a "successful" rebuild and the service keeps crash-looping at
full tilt. Observed 2026-09-18: nexus-web (:55059, pm2 id 17) served HTTP 500
Cannot read properties of null (reading 'prepare') for a day after a rebuild that had silently
no-opped, while the sibling tree nexus-equities/web rebuilt correctly only because its
package.json already carried an allowScripts entry.
The node ABI pair in play here: stale module built for NODE_MODULE_VERSION 127, runtime node
v24.21.0 reports 137. The error text is was compiled against a different Node.js version.
Related
- Crash-loop cost when this is left alone:
eq-webreached 227,402 pm2 restarts (~4/sec) and a 283 MB error log at ~4.2 KB/s growth. Checkpm2 describe <app>restart counts andwc -c ~/.pm2/logs/<app>-error.logbefore assuming a Node service is merely "online". pm2 flush <app>after a fix;~/.pm2/logsheld 586 MB, 290 MB after the flush.
Sources:
/Volumes/FATTY/src/nexus/package.json · /Volumes/FATTY/src/nexus-equities/web/package.json · npm 12.0.2 npm install-scripts ls output · session 2026-09-18 (cron)