On the 2.0-maintenance through 2.3-maintenance branches, running any Deno 2.9.x command in the checkout rewrites the per-package node_modules/ directories that pnpm created. Afterwards, pnpm pack fails for packages that depend on another workspace package, because the workspace links are gone:
ERR_PNPM_CANNOT_RESOLVE_WORKSPACE_PROTOCOL Cannot resolve workspace protocol of dependency "@fedify/fedify" because this dependency is not installed. Try running "pnpm install".
I ran into this while verifying #1255 on 2.0-maintenance, where I wanted to pack @fedify/cfworkers and install the tarball with npm.
Cause
The root deno.json on these branches sets "nodeModulesDir": "auto". With that setting, Deno 2.9 sets up its own node_modules/.deno/ tree and relinks every workspace member's node_modules/ to it. The relinked directory no longer has the workspace dependencies pnpm linked there (@fedify/fedify in the case of @fedify/cfworkers) or some tool dependencies (tsdown, typescript). Older Deno releases leave the pnpm links alone.
I checked a fresh pnpm install --ignore-scripts of 2.0-maintenance followed by deno check packages/cfworkers/src/mod.ts with several Deno versions:
| Deno |
packages/cfworkers/node_modules/@fedify/fedify |
| 2.7.13 |
intact |
| 2.8.3 |
intact |
| 2.9.1 |
removed |
| 2.9.5 |
removed |
| 2.9.7 |
removed |
The pinned versions in mise.toml (2.7.7 on 2.0 and 2.1, 2.7.13 on 2.2, and 2.8.3 on 2.3) do not trigger this, so CI is not affected. It happens locally whenever a Deno 2.9 binary runs in a maintenance-branch checkout. For example, this can happen when a shell or editor still has main's Deno 2.9.7 on its PATH after switching branches, or when a global Deno is used outside mise.
main and 2.4-maintenance are not affected. Their deno.json was switched to "nodeModulesDir": "none" in fab1c07 together with the upgrade to Deno 2.9.5.
Steps to reproduce
- Check out 2.0-maintenance (or 2.1–2.3) in a clean worktree.
- Run
pnpm install --ignore-scripts --frozen-lockfile.
- Run
deno check packages/cfworkers/src/mod.ts with Deno 2.9.x.
- Run
pnpm pack in packages/cfworkers/.
pnpm pack succeeds if you skip step 3.
Recovery is not obvious
A plain pnpm install restores the links, but in a normal checkout it also runs the root prepare script, which builds @fedify/vocab with deno task compile. If that deno is 2.9, the links are rewritten again right away, so pnpm install appears to have no effect. Running pnpm install --ignore-scripts, or making sure the pinned Deno is the one on PATH, recovers the checkout.
Possible fixes
- Backport
"nodeModulesDir": "none" to 2.0-maintenance through 2.3-maintenance, if those branches still work without Deno managing node_modules/ (main changed it as part of a larger toolchain upgrade, so this needs checking).
- Alternatively, document that maintenance branches must be used with their pinned Deno version, and add a check (e.g., in
mise run install) that fails early when the running Deno does not match mise.toml.
On the 2.0-maintenance through 2.3-maintenance branches, running any Deno 2.9.x command in the checkout rewrites the per-package node_modules/ directories that pnpm created. Afterwards,
pnpm packfails for packages that depend on another workspace package, because the workspace links are gone:I ran into this while verifying #1255 on 2.0-maintenance, where I wanted to pack
@fedify/cfworkersand install the tarball with npm.Cause
The root deno.json on these branches sets
"nodeModulesDir": "auto". With that setting, Deno 2.9 sets up its own node_modules/.deno/ tree and relinks every workspace member's node_modules/ to it. The relinked directory no longer has the workspace dependencies pnpm linked there (@fedify/fedifyin the case of@fedify/cfworkers) or some tool dependencies (tsdown,typescript). Older Deno releases leave the pnpm links alone.I checked a fresh
pnpm install --ignore-scriptsof 2.0-maintenance followed bydeno check packages/cfworkers/src/mod.tswith several Deno versions:The pinned versions in mise.toml (2.7.7 on 2.0 and 2.1, 2.7.13 on 2.2, and 2.8.3 on 2.3) do not trigger this, so CI is not affected. It happens locally whenever a Deno 2.9 binary runs in a maintenance-branch checkout. For example, this can happen when a shell or editor still has main's Deno 2.9.7 on its
PATHafter switching branches, or when a global Deno is used outside mise.main and 2.4-maintenance are not affected. Their deno.json was switched to
"nodeModulesDir": "none"in fab1c07 together with the upgrade to Deno 2.9.5.Steps to reproduce
pnpm install --ignore-scripts --frozen-lockfile.deno check packages/cfworkers/src/mod.tswith Deno 2.9.x.pnpm packin packages/cfworkers/.pnpm packsucceeds if you skip step 3.Recovery is not obvious
A plain
pnpm installrestores the links, but in a normal checkout it also runs the rootpreparescript, which builds@fedify/vocabwithdeno task compile. If thatdenois 2.9, the links are rewritten again right away, sopnpm installappears to have no effect. Runningpnpm install --ignore-scripts, or making sure the pinned Deno is the one onPATH, recovers the checkout.Possible fixes
"nodeModulesDir": "none"to 2.0-maintenance through 2.3-maintenance, if those branches still work without Deno managing node_modules/ (main changed it as part of a larger toolchain upgrade, so this needs checking).mise run install) that fails early when the running Deno does not match mise.toml.