What's the problem?
The fstat workaround added in #7070 and widened in #7104 still misses the v22 LTS line:
// .pnp.loader.mjs (Yarn 4.14.1)
const HAS_BROKEN_FSTAT_FOR_ZIP_FDS = major > 25 || (major === 25 && minor >= 7) || (major === 24 && minor >= 15);
The same family of ESM/module loader changes by Joyee Cheung (originals being nodejs/node#61769) was backported to Node v22.22.3 (released 2026-05-13), reproducing the identical EBADF: bad file descriptor, fstat.
Per nodejs/node#62012, v22.22.2 was reported as still working, so the regression hits at v22.22.3.
Relevant module/esm commits in v22.22.2...v22.22.3:
1769d74 esm: populate separate cache for require(esm) in imported CJS (Joyee Cheung)
12a2462 module: only put directly require-d ESM into require.cache (Joyee Cheung)
39147c1 module: use sync cjs when importing cts (Marco Ippolito)
2e91b28 module: handle null source from async loader hooks in sync hooks (Joyee Cheung)
9a2e213 module: do not wrap module._load when tracing is not enabled (Joyee Cheung)
5065a0a module: do not invoke resolve hooks twice for imported cjs (Joyee Cheung)
Especially nodejs/node#59929
Reproduction
$ node --version
v22.22.3
$ yarn --version
4.14.1
$ yarn run sql-ts # any CJS bin served from .yarn/cache zip
node:internal/modules/run_main:123
triggerUncaughtException(
^
Error: EBADF: bad file descriptor, fstat
at tryStatSync (node:fs:390:25)
at readFileSync (node:fs:446:17)
at getSourceSync (node:internal/modules/esm/load:41:14)
at defaultLoad (node:internal/modules/esm/load:92:34)
at nextLoad (node:internal/modules/esm/hooks:748:28)
at load$1 (file:///.../.pnp.loader.mjs:1526:12)
at nextLoad (node:internal/modules/esm/hooks:748:28)
at Hooks.load (node:internal/modules/esm/hooks:385:26)
at handleMessage (node:internal/modules/esm/worker:199:24)
at checkForMessages (node:internal/modules/esm/worker:141:28) {
errno: -9,
code: 'EBADF',
syscall: 'fstat'
}
Node.js v22.22.3
Works on Node v22.22.2 (per nodejs/node#62012), fails on v22.22.3.
Suggested fix
Widen the gate in packages/yarnpkg-pnp/sources/esm-loader/loaderFlags.ts:
export const HAS_BROKEN_FSTAT_FOR_ZIP_FDS =
major > 25 ||
(major === 25 && minor >= 7) ||
(major === 24 && minor >= 15) ||
(major === 22 && minor >= 22);
Strictly the regression starts at v22.22.3, but the existing gate is major.minor only, so (major === 22 && minor >= 22) over-covers v22.22.0..v22.22.2.
What's the problem?
The fstat workaround added in #7070 and widened in #7104 still misses the v22 LTS line:
The same family of ESM/module loader changes by Joyee Cheung (originals being nodejs/node#61769) was backported to Node v22.22.3 (released 2026-05-13), reproducing the identical
EBADF: bad file descriptor, fstat.Per nodejs/node#62012, v22.22.2 was reported as still working, so the regression hits at v22.22.3.
Relevant module/esm commits in
v22.22.2...v22.22.3:Especially nodejs/node#59929
Reproduction
Works on Node v22.22.2 (per nodejs/node#62012), fails on v22.22.3.
Suggested fix
Widen the gate in
packages/yarnpkg-pnp/sources/esm-loader/loaderFlags.ts:Strictly the regression starts at v22.22.3, but the existing gate is major.minor only, so
(major === 22 && minor >= 22)over-covers v22.22.0..v22.22.2.