Backstage "yarn install" better-sqlite3 node-gyp build fails in CI
The default Backstage backend depends on better-sqlite3, a native module. When no prebuilt binary matches the runner, node-gyp compiles it from source and needs python3 plus a C/C++ toolchain (build-essential) that a slim CI image does not have.
What this error means
yarn install fails inside better-sqlite3 with "gyp ERR! find Python" or "gyp ERR! stack Error: not found: make" and "prebuild-install warn install No prebuilt binaries found".
gyp ERR! find Python Python is not set from command line or npm configuration
gyp ERR! find Python checking if "python3" can be used
gyp ERR! find Python - "python3" is not in PATH or produced invalid output
gyp ERR! stack Error: Could not find any Python installation to use
error /app/node_modules/better-sqlite3: Command failed. Exit code: 1Common causes
No prebuilt binary for the runner, so node-gyp compiles
prebuild-install could not find a prebuilt better-sqlite3 for this Node ABI or platform, so it falls back to building from source with node-gyp.
The runner image has no python3 or compiler
node-gyp requires python3 and a working C/C++ toolchain. A minimal Node base image omits build-essential and Python, so the compile aborts.
How to fix it
Install python3 and build-essential before yarn
- Add a setup step that installs the build toolchain and Python.
- Run it before
yarn installso node-gyp finds its dependencies. - Re-run the install to compile better-sqlite3 from source.
sudo apt-get update
sudo apt-get install -y python3 make g++ build-essentialUse a Node image with build tools baked in
In Docker, base the build stage on an image that already ships the toolchain, or install it in the Dockerfile before copying package.json.
FROM node:20-bookworm
RUN apt-get update && apt-get install -y python3 g++ makeHow to prevent it
- Provision python3 and build-essential in the runner image, not per job.
- Pin the Node version so a matching prebuilt better-sqlite3 binary is used when available.
- Cache yarn and node_modules so the native build runs only when dependencies change.