Summary
@cldmv/uuid's exports map does not expose ./package.json, so:
require.resolve("@cldmv/uuid/package.json")
// ERR_PACKAGE_PATH_NOT_EXPORTED
even though the package is installed and its entry resolves perfectly well:
require.resolve("@cldmv/uuid")
// …/.pnpm/@cldmv+uuid@1.1.2/node_modules/@cldmv/uuid/index.cjs
Current map (v1.1.2) lists ., ./devcheck, ./main.
Why it matters
Resolving <name>/package.json is the conventional way tooling locates a package's directory on disk — you can't use the entry, because an exports map may point it anywhere, and you often need the package root rather than a module. Any tool doing dependency-graph or packaging work uses this, so a package that omits it breaks those tools specifically.
Worse, it breaks silently. The natural way to handle an unresolvable specifier is to skip it — optional deps and node: builtins land in the same bucket — so the omission turns into "this dependency quietly wasn't processed" rather than an error at the point of failure.
How it surfaced
@cldmv/rummage's web build stages each extension's dependency tree so extensions can run server-side. It resolved each dependency via <name>/package.json. That worked for every other package in the graph and threw here, so @cldmv/uuid was never staged.
The only symptom was several extensions failing to activate in a running server, with Cannot find package '@cldmv/uuid' — several layers away from the actual cause, and only visible at all because that build had just gained activation-failure logging.
rummage now falls back to resolving the entry and walking up to the owning package, so it tolerates this. But the fallback exists to work around a defect that shouldn't be there, and every other consumer has to write the same workaround.
Fix
{
"exports": {
".": { "…": "…" },
"./devcheck": { "…": "…" },
"./main": { "…": "…" },
"./package.json": "./package.json"
}
}
This is standard practice and has no downside — the file is already readable from the package directory; the exports map is the only thing preventing resolution through the specifier.
Related
A fleet-wide sweep to check every @cldmv/* package for this is tracked in packrat's docs/future-features.md (Repo hygiene sweeps) — packrat already scans every repo per profile, so it fits as a detector there. @cldmv/uuid is the one confirmed case so far; others are likely.
Summary
@cldmv/uuid'sexportsmap does not expose./package.json, so:even though the package is installed and its entry resolves perfectly well:
Current map (v1.1.2) lists
.,./devcheck,./main.Why it matters
Resolving
<name>/package.jsonis the conventional way tooling locates a package's directory on disk — you can't use the entry, because anexportsmap may point it anywhere, and you often need the package root rather than a module. Any tool doing dependency-graph or packaging work uses this, so a package that omits it breaks those tools specifically.Worse, it breaks silently. The natural way to handle an unresolvable specifier is to skip it — optional deps and
node:builtins land in the same bucket — so the omission turns into "this dependency quietly wasn't processed" rather than an error at the point of failure.How it surfaced
@cldmv/rummage's web build stages each extension's dependency tree so extensions can run server-side. It resolved each dependency via<name>/package.json. That worked for every other package in the graph and threw here, so@cldmv/uuidwas never staged.The only symptom was several extensions failing to activate in a running server, with
Cannot find package '@cldmv/uuid'— several layers away from the actual cause, and only visible at all because that build had just gained activation-failure logging.rummage now falls back to resolving the entry and walking up to the owning package, so it tolerates this. But the fallback exists to work around a defect that shouldn't be there, and every other consumer has to write the same workaround.
Fix
{ "exports": { ".": { "…": "…" }, "./devcheck": { "…": "…" }, "./main": { "…": "…" }, "./package.json": "./package.json" } }This is standard practice and has no downside — the file is already readable from the package directory; the
exportsmap is the only thing preventing resolution through the specifier.Related
A fleet-wide sweep to check every
@cldmv/*package for this is tracked in packrat'sdocs/future-features.md(Repo hygiene sweeps) — packrat already scans every repo per profile, so it fits as a detector there.@cldmv/uuidis the one confirmed case so far; others are likely.