The error, verbatim
Jump to the fix ↓Error: Could not locate the bindings file. Tried:
→ C:\project\node_modules\better-sqlite3\build\better_sqlite3.node
→ C:\project\node_modules\better-sqlite3\build\Debug\better_sqlite3.node
→ C:\project\node_modules\better-sqlite3\build\Release\better_sqlite3.node
→ C:\project\node_modules\better-sqlite3\out\Debug\better_sqlite3.node
...
Tested on
- sqlite3
- 6.0.1
- better-sqlite3
- 12.11.1 / 13.0.3
- Node
- 24.14.0 / 26.10.0
- npm
- 11.9.0 / 12.2.0
- Bundler
- esbuild 0.28.2
- OS
- Windows 11 Pro
Contents
Both SQLite packages are native modules: JavaScript plus a compiled .node file. The bindings helper they load it with searches a list of folders, and this error is it reporting that every folder came up empty. The paths after “Tried:” tell you which cause you have, so read them before trying anything.
Read the “Tried:” paths first
| The paths point into… | Cause | Go to |
|---|---|---|
node_modules\sqlite3\build\… or node_modules\better-sqlite3\build\… |
The .node file was never built or downloaded |
1 |
your project’s own build\… (no node_modules in the path) |
A bundler copied the code but not the .node file |
2 |
If the message instead says was compiled against a different Node.js version using NODE_MODULE_VERSION, the file exists but was built for another Node: go to 3.
1. The build step never ran
sqlite3 (even the current 6.0.1) and better-sqlite3 before version 13 don’t ship a ready .node file. Their install script downloads a prebuilt one, or compiles it. Skip the script and the folder stays empty, while npm install still prints success. I reproduced this three ways:
npm install --ignore-scripts, common in CI and Docker builds.- npm 12, which blocks dependency install scripts by default:
sqlite3@6.0.1 (install: prebuild-install -r napi || node-gyp rebuild)in the warning after the install. What else npm 12 breaks. - better-sqlite3 12.x with either of the above. Its script is
prebuild-install || node-gyp rebuild --release.
Run the skipped script now:
npm rebuild sqlite3(or npm rebuild better-sqlite3)
On npm 12, approve the script so the next install doesn’t skip it again:
npm install-scripts approve sqlite3
npm rebuild2. A bundler packed the module
When esbuild, webpack or a similar tool bundles better-sqlite3, the JavaScript moves into your bundle but the .node file doesn’t. bindings then searches next to the bundle, which is why the paths lose node_modules:
Error: Could not locate the bindings file. Tried:
→ C:\project\build\better_sqlite3.node
→ C:\project\build\Debug\better_sqlite3.node
→ C:\project\build\Release\better_sqlite3.node
That’s better-sqlite3 12 bundled with esbuild. Version 13 fails differently but for the same reason: Cannot find module 'C:\project\build\Release\better_sqlite3.node'.
Keep native modules out of the bundle, so they load from node_modules at runtime:
npx esbuild app.cjs --bundle --platform=node --outfile=dist/out.cjs --external:better-sqlite3Other tools have the same switch under their own names (external in Rollup, Vite and webpack, serverExternalPackages in Next.js); I tested only esbuild.
3. You switched Node versions (a different error)
Switching Node with nvm or upgrading it doesn’t produce this error for better-sqlite3 12; you get its cousin:
The module '…\better-sqlite3\build\Release\better_sqlite3.node'
was compiled against a different Node.js version using
NODE_MODULE_VERSION 137. This version of Node.js requires …
Rebuild with the Node you’re going to run:
npm rebuild better-sqlite3sqlite3 doesn’t have this problem: its binary uses Node’s stable N-API, and the one built under Node 24 ran unchanged on Node 26. better-sqlite3 13 also worked on both without a rebuild.
What didn’t work
How this was tested
Fresh projects on Windows 11, Node 24.14.0 and 26.10.0, npm 11.9.0 and 12.2.0. Each package was installed with scripts skipped (--ignore-scripts and npm 12’s default), run, then fixed and run again with select 1. The Node switch was tested by running one install under both Node versions, and bundling by building with esbuild 0.28.2 with and without --external. Error text is copied from those runs, with my scratch path shortened to C:\project.
— N.K., end of entry No.042