Liferay JS Bundler Breaking (Broken) Change

A panic went up today as builds using Liferay's JS bundler started breaking. Here's the issue and the solution...

Fixing broken npm bundler builds

So I wasn't planning on writing this blog today, but it is hitting a lot of people and I'm sure there's going to be a slew of reported issues on this, so I felt I should get the word out...

If you are doing a build that involves the Liferay JS npm bundler, you may get errors such as:

node:internal/fs/utils:344
    throw err;
    ^

Error: ENOENT: no such file or directory, open '/var/jenkins_home/workspace/.../liferay/modules/common-js-bundle/build/node_modules/lodash@4.17.21/minBy.js'
    at Object.openSync (node:fs:585:3)
    at Object.writeFileSync (node:fs:2153:35)
    at /var/jenkins_home/workspace/.../liferay/node_modules/liferay-npm-bundler/lib/steps/transform.js:179:36
    at /var/jenkins_home/workspace/.../liferay/node_modules/babel-core/lib/api/node.js:143:7
    at FSReqCallback.readFileAfterClose [as oncomplete] (node:internal/fs/read_file_context:68:3) {
  errno: -2,
  syscall: 'open',
  code: 'ENOENT',
  path: '/var/jenkins_home/workspace/.../liferay/modules/common-js-bundle/build/node_modules/lodash@4.17.21/minBy.js'
}

or

Task :modules:my-project:my-project-web:packageRunBuild
> my-project-web@1.0.0 build /builds/dxp-7.2/intranet-devops/my-workspace/modules/my-project/my-project-web
> babel --source-maps -d build src && npm run copy-assets && liferay-npm-bundler
Successfully compiled 4 files with Babel (1607ms).
> my-project-web@1.0.0 copy-assets /builds/dxp-7.2/intranet-devops/my-workspace/modules/my-project/my-project-web
> lnbs-copy-assets
Project assets copied.
Error: ENOENT: no such file or directory, open '/builds/dxp-7.2/intranet-devops/my-workspace/modules/my-project/my-project-web/build/node_modules/loose-envify@1.4.0/cli.js'
    at Object.openSync (fs.js:438:3)
    at Object.readFileSync (fs.js:343:35)
    at loadSourceMap (/builds/dxp-7.2/intranet-devops/my-workspace/modules/my-project/my-project-web/node_modules/liferay-npm-bundler/lib/steps/transform.js:208:44)
    at Promise (/builds/dxp-7.2/intranet-devops/my-workspace/modules/my-project/my-project-web/node_modules/liferay-npm-bundler/lib/steps/transform.js:168:29)
    at new Promise (<anonymous>)
    at babelifyFile (/builds/dxp-7.2/intranet-devops/my-workspace/modules/my-project/my-project-web/node_modules/liferay-npm-bundler/lib/steps/transform.js:153:12)
    at util_1.runInChunks (/builds/dxp-7.2/intranet-devops/my-workspace/modules/my-project/my-project-web/node_modules/liferay-npm-bundler/lib/steps/transform.js:143:104)
    at Promise.all.chunk.map (/builds/dxp-7.2/intranet-devops/my-workspace/modules/my-project/my-project-web/node_modules/liferay-npm-bundler/lib/steps/util.js:85:44)
    at Array.map (<anonymous>)
    at runInChunks (/builds/dxp-7.2/intranet-devops/my-workspace/modules/my-project/my-project-web/node_modules/liferay-npm-bundler/lib/steps/util.js:85:30)
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! my-project-web@1.0.0 build: `babel --source-maps -d build src && npm run copy-assets && liferay-npm-bundler`
npm ERR! Exit status 1
npm ERR! 
npm ERR! Failed at the my-project-web@1.0.0 build script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
npm ERR! A complete log of this run can be found in:
npm ERR!     /root/.npm/_logs/2025-01-08T19_53_34_131Z-debug.log
> Task :modules:my-project:my-project-web:packageRunBuild FAILED
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':modules:my-project:my-project-web:packageRunBuild'.
> Process 'command '/builds/d

So these kinds of failures were due to an unexpected (and I believe unannounced) update to the Liferay NPM bundler.

Fortunately it is super easy to fix...

For workspaces with liferay.workspace.node.package.manager unset or set to yarn, you can use the resolutions field in the workspace's root package.json (docs):

{
  "resolutions": {
    "fast-glob": "3.3.2"
  }
}

For workspaces with liferay.workspace.node.package.manager set to npm, you can use the overrides field in each module's package.json (docs):

{
  "overrides": {
    "fast-glob": "3.3.2"
  }
}

I'm still not sure what changed, why it was changed outside of a release cycle, and more importantly why it was not announced, but if I get more information I'll be sure to share it.

At least now you have a quick solution to get your builds working again...

Update #1

So I found out the reason for the breakage, it's one many of us who are javascript developers have run into:

about the specific reason why this is happening...

liferay-npm-bundler uses globby to select which files it will process in each package of a JS module, which amounts to the module itself and each of its direct and transitive dependencies

the globby version used by liferay-npm-bundler has been unmaintained for a few years, but internally it uses fast-glob which had a new version released on 2025-01-05

this new version changed how it handles absolute negative patterns liferay-npm-bundler uses those patterns to exclude nested dependency files from node_modules folders when processing each package

with it broken, multiple packages can select the same files for processing

but when one of the packages is done processing, it moves the file to a new location
when this happens, any other concurrent attempt to process the same file will fail with a ENOENT error

basically a transitive dependency outside of our control was updated recently and it breaks liferay-npm-bundler

this is a problem on workspaces that do not have lockfiles pinning its JS dependency graph, so every builds gets a new resolution of dependencies with the latest ones available

So yeah, this is something that I'm sure most of us have hit in the past.

The solution posted above will work to fix the version of globby and avoid the updated version and should work at least until the npm bundler gets updated to be compatible with the newer globby release.

Update #2

Liferay just published a new version of the Liferay NPM Bundler tool which works for the old and new versions of globby...

As long as you're using version 2.32.1 or later, you shouldn't need the short term fix listed above.