[Bug?]: `fsBinding.cpSyncCheckPaths` error in Node 22
Self-service
- [ ] I'd be willing to implement a fix
Describe the bug
I have a monorepo with a build script that calls fs.cpSync to copy Yarn-installed dependencies into a build directory. When using Yarn and Node 20, it works fine. When using Yarn and Node 22, it fails with
Copying /private/tmp/test/.yarn/cache/semver-npm-7.6.3-57e82c14d5-88f33e148b.zip/node_modules/semver/package.json to semver.json...
node:internal/fs/cp/cp-sync:56
fsBinding.cpSyncCheckPaths(src, dest, opts.dereference, opts.recursive);
^
Error: Unknown system error 17: Unknown system error 17, lstat '/private/tmp/test/.yarn/cache/semver-npm-7.6.3-57e82c14d5-88f33e148b.zip/node_modules/semver/package.json'
at cpSyncFn (node:internal/fs/cp/cp-sync:56:13)
at Object.cpSync (node:fs:3044:3)
at Object.<anonymous> (/private/tmp/test/packages/foo/index.cjs:7:4)
at Module._compile (node:internal/modules/cjs/loader:1546:14)
at Module._extensions..js (node:internal/modules/cjs/loader:1691:10)
at require$$0.Module._extensions..js (/private/tmp/test/.pnp.cjs:5699:33)
at Module.load (node:internal/modules/cjs/loader:1317:32)
at Module._load (node:internal/modules/cjs/loader:1127:12)
at require$$0.Module._load (/private/tmp/test/.pnp.cjs:5547:31)
at TracingChannel.traceSync (node:diagnostics_channel:315:14) {
errno: 17,
code: 'Unknown system error 17',
syscall: 'lstat',
path: '/private/tmp/test/.yarn/cache/semver-npm-7.6.3-57e82c14d5-88f33e148b.zip/node_modules/semver/package.json'
}
Node.js v22.6.0
To reproduce
You can use the following script to reproduce. For example,
nvm use 20
sh repro.sh
should succeed, while
nvm use 22
sh repro.sh
should fail. Here is the script, repro.sh:
set -ex
cat >package.json <<EOF
{
"name": "test",
"packageManager": "[email protected]",
"workspaces": [
"packages/*"
]
}
EOF
mkdir -p packages/foo
cat >packages/foo/package.json <<EOF
{
"name": "foo",
"version": "1.0.0",
"main": "index.cjs",
"dependencies": {
"semver": "*"
}
}
EOF
cat >packages/foo/index.cjs <<EOF
const fs = require('fs')
const path = require('path')
const src = path.join(require.resolve('semver'), '..', 'package.json')
const dst = path.join('.', 'semver.json')
console.log(\`Copying \${src} to \${dst}...\`)
fs.cpSync(src, dst)
EOF
yarn install
yarn workspace foo exec node ./index.cjs
Environment
System:
OS: macOS 14.5
CPU: (8) arm64 Apple M2
Binaries:
Node: 22.6.0 - /private/var/folders/z5/r01rjpb57_d5ggd6zg8q7dg00000gp/T/xfs-69bfefa1/node
Yarn: 4.4.1 - /private/var/folders/z5/r01rjpb57_d5ggd6zg8q7dg00000gp/T/xfs-69bfefa1/yarn
npm: 10.8.2 - ~/.nvm/versions/node/v22.6.0/bin/npm
Additional context
No response
I can workaround this by using cp from fs/promises 👍
It looks like https://github.com/nodejs/node/pull/53614 introduces cpSyncCheckPaths, and perhaps this needs patching in @yarnpkg/fslib?
I just ran into a similar (the same?) issue when trying to migrate away from fs-extra to using native node:fs methods.
- fse.copySync(templateDir, newAppDir, { overwrite })
+ fs.cpSync(templateDir, newAppDir, { recursive: true, force: overwrite })
And here's the error message I'm getting
node:internal/fs/cp/cp-sync:56
fsBinding.cpSyncCheckPaths(src, dest, opts.dereference, opts.recursive);
^
Error: ENOTDIR: not a directory, lstat '/home/runner/.yarn/berry/cache/create-cedar-app-file-313a48fa7e-10c0.zip/node_modules/create-cedar-app/templates/ts'
at cpSyncFn (node:internal/fs/cp/cp-sync:56:13)
at Object.cpSync (node:fs:3147:3)
at $ce (file:///home/runner/.yarn/berry/cache/create-cedar-app-file-313a48fa7e-10c0.zip/node_modules/create-cedar-app/dist/create-cedar-app.js:583:816)
at async rue (file:///home/runner/.yarn/berry/cache/create-cedar-app-file-313a48fa7e-10c0.zip/node_modules/create-cedar-app/dist/create-cedar-app.js:598:857)
at async file:///home/runner/.yarn/berry/cache/create-cedar-app-file-313a48fa7e-10c0.zip/node_modules/create-cedar-app/dist/create-cedar-app.js:599:183
at async file:///home/runner/.yarn/berry/cache/create-cedar-app-file-313a48fa7e-10c0.zip/node_modules/create-cedar-app/dist/create-cedar-app.js:599:128 {
errno: -20,
code: 'ENOTDIR',
syscall: 'lstat',
path: '/home/runner/.yarn/berry/cache/create-cedar-app-file-313a48fa7e-10c0.zip/node_modules/create-cedar-app/templates/ts'
}
Sysinfo
System:
OS: macOS 15.2
Shell: 5.9 - /bin/zsh
Binaries:
Node: 24.12.0 - /private/var/folders/7j/9p56mwmj6jsfdr2h5_884j9w0000gn/T/xfs-6c7bc5a8/node
Yarn: 4.12.0 - /private/var/folders/7j/9p56mwmj6jsfdr2h5_884j9w0000gn/T/xfs-6c7bc5a8/yarn
Using await fs.promises.cp() as a workaround worked for me as well