Creating .patch-file not working with NPM overrides having (shared) nested dependency
Not sure if bug or (not yet implemented) feature.
NPM supports changing and even replacing (transitive) dependencies via the "overrides" node in the package.json, this is a NPM feature since v8 (not sure since when exactly):
- v8 documentation https://docs.npmjs.com/cli/v8/configuring-npm/package-json?v=true#overrides
- v9 documentation https://docs.npmjs.com/cli/v9/configuring-npm/package-json?v=true#overrides
I now have this interesting example where I want to replace a (transitive) dependency with a different dependency (not only a different version) in order to get rid of bugs/in order to increase build-speed/because the lib got reworked under different package coordinates:
{
"name": "some-patch-package-thing",
"version": "0.0.0",
"private": true,
"scripts": {
"postinstall": "patch-package"
},
"dependencies": {
"react-use": "^17.4.0"
},
"devDependencies": {
"patch-package": "^6.5.1",
"postinstall-postinstall": "^2.1.0",
"react-scripts": "5.0.1"
},
"engines": {
"node": ">= 18.14.0"
},
"overrides": {
"magic-string": {
"sourcemap-codec": "@jridgewell/sourcemap-codec@^1.4.14"
},
"nano-css": {
"sourcemap-codec": "@jridgewell/sourcemap-codec@^1.4.14"
},
"svgo": {
"nth-check": "2.1.1"
}
}
}
After npm install all dependencies are getting downloaded, but as magic-string and nano-css are now sharing the same version, the node_modules-folder contain a symlink to the real package. Having two dependencies sharing the same version of a transitive dependency is KEY to this bug. Having only magic-string does not recreate the problem.
Here a tree-output of the magic-string in node_modules:
| index.d.ts
| LICENSE
| package.json
| README.md
|
+---dist
| magic-string.cjs.js
| magic-string.cjs.js.map
| magic-string.es.js
| magic-string.es.js.map
| magic-string.umd.js
| magic-string.umd.js.map
|
\---node_modules
\---sourcemap-codec
After download is finished I need to adjust the magic-string-package to reflect the new @jridgewell/sourcemap-codec coordinates, so I edit the files node_modules/magic-string/dist/magic-string.cjs.js and node_modules/magic-string/dist/magic-string.es.js.
Now here comes the problem: when I run npx patch-package magic-string after my edits, to create a patch-file (as normal), I will get greeted with a weird warning:

(Text version of the screenshot, to improve searchability)
patch-package 6.5.1
• Creating temporary folder
• Installing [email protected] with npm
• Diffing your files with clean files
Error: ENOENT: no such file or directory, stat 'C:\develop\tmp\some-patch-package-thing\node_modules\magic-string\node_modules\sourcemap-codec'
at Object.statSync (node:fs:1596:3)
at Object.statSync (C:\develop\tmp\some-patch-package-thing\node_modules\graceful-fs\polyfills.js:318:34)
at statSync (C:\develop\tmp\some-patch-package-thing\node_modules\fs-extra\lib\util\stat.js:10:52)
at getStatsSync (C:\develop\tmp\some-patch-package-thing\node_modules\fs-extra\lib\util\stat.js:24:19)
at Object.checkPathsSync (C:\develop\tmp\some-patch-package-thing\node_modules\fs-extra\lib\util\stat.js:49:33)
at copyDirItem (C:\develop\tmp\some-patch-package-thing\node_modules\fs-extra\lib\copy-sync\copy-sync.js:121:29)
at C:\develop\tmp\some-patch-package-thing\node_modules\fs-extra\lib\copy-sync\copy-sync.js:115:39
at Array.forEach (<anonymous>)
at copyDir (C:\develop\tmp\some-patch-package-thing\node_modules\fs-extra\lib\copy-sync\copy-sync.js:115:23)
at mkDirAndCopy (C:\develop\tmp\some-patch-package-thing\node_modules\fs-extra\lib\copy-sync\copy-sync.js:110:3) {
errno: -4058,
syscall: 'stat',
code: 'ENOENT',
path: 'C:\\develop\\tmp\\some-patch-package-thing\\node_modules\\magic-string\\node_modules\\sourcemap-codec'
}
C:\develop\tmp\some-patch-package-thing\node_modules\patch-package\dist\makePatch.js:218
throw e;
^
This probably is due to the node_modules folder not existing in the one which gets downloaded on the • Installing [email protected] with npm step. I have not tested this on MacOS or Linux systems.
OS: Windows 10 Pro Node: v18.14.0 NPM: 9.4.2
In situations like this, I just did the override at my top level package.json, while waiting for the underlying package to get fixed.