Vite-plugin-wasm-pack with buildNpmModule fails on file permission

I am trying to make a derivation for static site using vite-plugin-wasm-pack and astro (astro is not really important here, but it uses vite under the hood), which utilizes some rust wasm code I’ve built with wasm-pack. The derivation to build the wasm-pack output the correct files. The purpose of vite-plugin-wasm-pack (as I understand it) is to do a simple transformation of the files, put it into node_modules/ and register it with vite.

I’m getting some problems running it via nix. The project has a flake set up, and the “local” build works correctly (npm run build on the cli). Using pkgs.buildNpmPackage in nix though seemingly no matter what I do I gets the following error:

Error: EACCES: permission denied, open 'node_modules/solver/solver.js'
    at Object.openSync (node:fs:603:3)
    at Object.writeFileSync (node:fs:2324:35)
    at prepareBuild (/build/site/node_modules/vite-plugin-wasm-pack/dist/index.js:129:36)
    at async Context.buildStart (/build/site/node_modules/vite-plugin-wasm-pack/dist/index.js:132:17)
    at async Promise.all (index 3)
    at async hookParallel (file:///build/site/node_modules/vite/dist/node/chunks/dep-2b82a1ce.js:43920:9)
    at async Object.buildStart (file:///build/site/node_modules/vite/dist/node/chunks/dep-2b82a1ce.js:44244:13)
    at async file:///build/site/node_modules/vite/dist/node/chunks/dep-2b82a1ce.js:65302:13
    at async _createServer (file:///build/site/node_modules/vite/dist/node/chunks/dep-2b82a1ce.js:65332:9)
    at async syncInternal (file:///build/site/node_modules/astro/dist/core/sync/index.js:32:26)

The interesting bits of the build are this: = pkgs.buildNpmPackage {
  src = ./site;
  buildInputs = [
    solver-crate # This is the wasm-pack derivation
  ] ++ (with pkgs; [

  buildPhase = ''
    echo "Running Pre Build!"
    mkdir -p solver
    echo "Tree Solver Crate"

    cp -R ${solver-crate}/pkg solver

    echo "Running Build"
    # Verify the contents of `solver` directory
    ${pkgs.tree}/bin/tree solver
    # Desparately try to change the permissions of node_modules/
    mv node_modules node_modules_pre
    cp -R  node_modules_pre node_modules
    mkdir node_modules/solver/
    chmod -R a+rwx node_modules

    # Try force the file to exist (this line changes nothing..)
    touch node_modules/solver/solver.js
    # Re-run the permissions change
    chmod -R a+rwx node_modules/solver/*
    # Debug output the permissions of the solver directory
    ls -lah node_modules/solver

    # Actually run build (where we fail.)
    npm run build --unsafe-perm=true

  installPhase = ''
    mkdir $out
    cp -R public/* $out

The log output here shows me that both my crate is showing up in the correct location, and has the correct files. And I don’t understand the permission issue, as I’ve given the destination file all the permissions possible and created the directory myself. I know this isn’t the nix way, but I don’t know what else to do.

buildNpmPackage uses fetchNpmDeps under the hood, so I assume this is a different derivation, which is why I thought copying the directory might be a way to get around the issue. Without wasm-pack integration (so just a new astro site), then buildNpmPackage works totally fine and I can build the static site. It’s not until I introduce the very necessary vite-plugin-wasm-pack that I run into issues.

I would greatly appreciate any insights! I’ve been banging my head on this problem for a few days now.

Finally figured this out; fs.copyFile fails with permission denied even when dest folder is writable · Issue #37285 · nodejs/node · GitHub

Copying the file from the solver/pkg file is what was failing, because even if node has permission to write to the output directory, if the input file is read-only this doesn’t work.

Solution was to copy in and change the permissions on the files generated in my previous wasm-pack derivation