Pnpm building a package (better-sqlite3)

I’m trying to build a pnpm-based node app with nix, but I’m having trouble with a specific package, better-sqlite3. I run pnpm rb (rebuild) in the build phase to run the install scripts for my packages, since the pnpm.configHook omits them; however, better-sqlite3 silently fails to build no matter what I seem to do. This is only an issue when building with nix (the app works normally when I do things the more usual way). There are some other packages that need pnpm rb, and they work fine—it’s just this one specific package I’m having issues with. The tail of the log just has a bunch of empty lines.

I’ve tried many things (patching better-sqlite3 to write debug information to a file, copying the config hook to a custom build script and running the package install scripts at install time, manually putting node-gyp and python314 into buildInputs, etc.), but no luck.

My question is twofold:

  • How do I fix this issue?
  • How can I debug this sort of thing in the future?

Here’s the tail of the log:

Running phase: buildPhase
@nix { "action": "setPhase", "phase": "buildPhase" }
<some successful package builds>
node_modules/.pnpm/better-sqlite3@11.8.1/node_modules/better-sqlite3: Running install script...
node_modules/.pnpm/better-sqlite3@11.8.1/node_modules/better-sqlite3: Running install script, failed in 225ms
.../node_modules/better-sqlite3 install$ 
│ 
│ 
│ 
│ 
│ 
│ 
│ 
│ 
│ 
│ 
│ 
│

Here’s a sample flake.nix:

{
  description = "My app";
  inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
  inputs.systems.url = "github:nix-systems/default";
  inputs.flake-utils = {
    url = "github:numtide/flake-utils";
    inputs.systems.follows = "systems";
  };

  outputs = { nixpkgs, flake-utils, self, ... }:
    flake-utils.lib.eachDefaultSystem (system:
      let
        pkgs = nixpkgs.legacyPackages.${system};
        self-packages = self.packages.${system};
        pnpm = pkgs.pnpm_10;
      in
      {
        devShells.default = pkgs.mkShell { packages = [
          pkgs.bashInteractive
          pkgs.nodejs
          pnpm
        ]; };

        packages.default = pkgs.stdenv.mkDerivation {
          pname = "my-app";
          version = "0.1.0";
          src = ./.;
          buildInputs = [ pkgs.nodejs pnpm.configHook ];

          buildPhase = ''
            pnpm rb
            pnpm run build
          '';

          installPhase = ''
            mkdir -p $out
            cp package.json $out
            cp -r node_modules $out
            cp -r src $out
          '';

          pnpmDeps = pnpm.fetchDeps {
            inherit (self-packages.default) pname version src;
            hash = "sha256-vYsjdAZ4ceJ6sHZwNboL/wvS47RvMLx8bmWWB5v3/SM=";
          };
        };
      }
    );
}

and package.json:

{
  "name": "my-app",
  "private": true,
  "version": "0.1.0",
  "scripts": {
    "build": "echo 'insert build here'"
  },
  "dependencies": {
    "better-sqlite3": "^11.8.1"
  },
  "pnpm": {
    "onlyBuiltDependencies": [
      "better-sqlite3"
    ]
  }
}