Skip to content

Conversation

@colincasey
Copy link
Contributor

@colincasey colincasey commented Dec 11, 2025

When a cacheDirectories field is set in package.json, this triggers custom cache behavior in the buildpack. This is often used with tools that produce their own specialized caches like Next.js which can cache asset compilation results.

Since custom cache behavior means the user is taking full control of what needs to be cached, the node_modules folder is typically added to the cache directory list to ensure that installed modules are also cached. For npm and Yarn this doesn't present a problem but, for pnpm, the node_modules folder is used differently and, if the folder already exists (e.g.; on cache restore), it will cause the build to halt with an ERR_PNPM_ABORTED_REMOVE_MODULES_DIR_NO_TTY error.

After examining the custom cache code, I'm certain that even how npm and Yarn handle this scenario is incorrect. The user should never cache the node_modules folder. What should happen instead is (for default or custom cache behavior), the npm cache, Yarn cache, and pnpm store are what should be always cached unless NODE_MODULES_CACHE=false. For now, I'm just going to address this pnpm case though. This PR makes the following changes:

Custom Cache Behavior with pnpm

  • if node_modules is specified, it will be ignored
  • all other cache directories will be processed
  • the pnpm store will be inserted into the custom cache list

pnpm Reporter

A PNPM_INSTALL_REPORTER environment variable was introduced to allow for more detailed pnpm output to be produced during install. If set it, the value of this environment variable will be used to append the --reporter argument when pnpm install is executed. This is used by the tests in this PR to ensure that the pnpm store is functioning correctly, but it could also be useful when debugging builds where pnpm installs are failing unexpectedly.

W-20494168

Fixes #1518

When a `cacheDirectories` field is set in `package.json`, this triggers [custom cache behavior](https://devcenter.heroku.com/articles/nodejs-classic-buildpack-builds#custom-caching) in the buildpack. This is often used with tools that produce their own specialized caches like Next.js which can cache asset compilation results.

Since custom cache behavior means the user is taking full control of what needs to be cached, the `node_modules` folder is typically added to the cache directory list to ensure that installed modules are also cached. For npm and Yarn this doesn't present a problem but, for pnpm, [the `node_modules` folder is used differently](https://pnpm.io/motivation#creating-a-non-flat-node_modules-directory) and, if the folder already exists (e.g.; on cache restore), it will cause the build to halt with an `ERR_PNPM_ABORTED_REMOVE_MODULES_DIR_NO_TTY` error.

After examining the custom cache code, I'm certain that even how npm and Yarn handle this scenario is incorrect. The user should never cache the `node_modules` folder. What should happen instead is (for default or custom cache behavior), the npm cache, Yarn cache, and pnpm store are what should be always cached unless `NODE_MODULES_CACHE=false`. For now, I'm just going to address this pnpm case though. This PR makes the following changes:

### Custom Cache Behavior with pnpm

- if `node_modules` is specified, it will be ignored
- all other cache directories will be processed
- the pnpm store will be inserted into the custom cache list

### pnpm Reporter

A `PNPM_INSTALL_REPORTER` environment variable was introduced to allow for more detailed pnpm output to be produced during install. If set it, the value of this environment variable will be used to append the [`--reporter`](https://pnpm.io/cli/install#--reportername) argument when `pnpm install` is executed. This is used by the tests in this PR to ensure that the pnpm store is functioning correctly, but it could also be useful when debugging builds where pnpm installs are failing unexpectedly.
Signed-off-by: Colin Casey <[email protected]>
@colincasey colincasey self-assigned this Dec 11, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Rebuild failure with pnpm + custom cache dir configuration that includes node_modules

1 participant