How to Install better-sqlite3 in CI
better-sqlite3 is a fast synchronous SQLite binding. In CI it breaks on ABI mismatches and on platforms without a prebuilt binary.
better-sqlite3 publishes prebuilt binaries via prebuild for common Node versions and platforms. Mismatched Node ABI or a missing prebuilt forces a source build that needs Python and a compiler.
Why it fails in CI
- The runner Node ABI differs from the one the prebuilt binary targets →
NODE_MODULE_VERSIONmismatch. - Alpine/musl or an uncommon arch has no prebuilt → source build needs python3 + g++.
- A node_modules cached under a different Node version carries an incompatible binary.
Install it reliably
Install fresh on the target Node version. If a source build is triggered, provide the toolchain. Rebuild after any Node version change.
# clean install on the target Node version
npm ci
# Alpine / forced source build
apk add --no-cache python3 make g++
npm install better-sqlite3 --build-from-source
# after switching Node versions, rebuild the native addon
npm rebuild better-sqlite3Cache & speed
Cache ~/.npm keyed on lockfile + Node version. If you cache node_modules, include the Node version in the key so an ABI change invalidates it.
- uses: actions/cache@v4
with:
path: ~/.npm
key: npm-${{ runner.os }}-node${{ matrix.node }}-${{ hashFiles('**/package-lock.json') }}Common errors
The module ... was compiled against a different Node.js version using NODE_MODULE_VERSION→ runnpm rebuild better-sqlite3on the target Node.prebuild-install warn install No prebuilt binaries found→ install python3 + g++ for the source build.Could not locate the bindings file→ the build failed; check the toolchain.
Key takeaways
- Match the prebuilt binary to the runner Node ABI, or rebuild from source.
- Run
npm rebuild better-sqlite3after changing Node versions. - Alpine/musl source builds need python3 + g++.