denoland/deno · error · anyhow::Error
unable to find npm package in workspace
Error message
unable to find npm package in workspace
What it means
When publishing to JSR, Deno rewrites ('unfurls') npm specifiers found in published source into pinned versions. For a package expected to be an npm workspace member, `find_workspace_npm_dep_version` searches every workspace package.json for one whose `name` matches; finding none produces this error. A source todo (#24612) notes a missing warning for packages that are also published to JSR.
Source
Thrown at cli/tools/publish/unfurl.rs:675
referrer,
relative_resolved
);
Ok(Some(relative_resolved))
}
}
fn find_workspace_npm_dep_version(
&self,
pkg_name: &str,
) -> Result<Version, anyhow::Error> {
// todo(#24612): warn when this is also a jsr package telling
// people to map the specifiers in the import map
let pkg_json = self
.workspace_resolver
.package_jsons()
.find(|pkg| pkg.name.as_deref() == Some(pkg_name))
.ok_or_else(|| {
anyhow::anyhow!("unable to find npm package in workspace")
})?;
if let Some(version) = &pkg_json.version {
Ok(Version::parse_from_npm(version)?)
} else {
Err(anyhow::anyhow!(
"missing version in package.json of npm package",
))
}
}
/// Look up the version constraint for a @types/* package from package.json
/// dependencies (including devDependencies) or from the import map.
fn find_types_package_version_req(
&self,
types_package_name: &str,
referrer: &ModuleSpecifier,
) -> Option<VersionReq> {
// check package.json dependenciesView on GitHub (pinned to 89f33cbef2)
Solutions
- Add the npm package as a workspace member whose package.json `"name"` exactly matches the imported package name
- If the package was renamed, update the imports to the new name
- Change the specifier to a plain `npm:package@version` dependency instead of a workspace reference
Example fix
// before — importer uses npm:shared-lib but member name diverges
// packages/shared/package.json
{ "name": "@acme/shared-lib", "version": "0.1.0" }
// after — names match
{ "name": "shared-lib", "version": "0.1.0" } Defensive patterns
Strategy: validation
Validate before calling
# before publish: every npm: specifier treated as a workspace dep must
# match some member package.json "name"
grep -rhoE 'npm:[@a-z0-9-]+(/[a-z0-9._-]+)?@?[^"'"'']*' src --include='*.ts' | sort -u \
| while read -r spec; do
name=$(echo "$spec" | sed -E 's|^npm:||; s|@[^/]*$||; s|(@[^/]+)$|\1|')
found=$(find . -name package.json -not -path '*/node_modules/*' \
-exec grep -l "\"name\": \"$name\"" {} +)
[ -n "$found" ] || echo "no workspace member named: $name"
done Prevention
- Keep member package.json `name` fields in lockstep with the specifiers importers use
- When removing or renaming an npm workspace member, grep for its specifier before publishing
- Run `deno publish --dry-run` — unfurling errors surface there without uploading
When it happens
Trigger: Published source (or its import-map resolution) references an npm package as a workspace dependency, but no workspace member's package.json has `"name"` equal to that package name — the member was removed, renamed, or never existed in the workspace.
Common situations: Monorepos mixing JSR and npm packages; renaming a package in package.json without updating importers; deleting a member while imports remain; import maps pointing at packages that are not workspace members.
Related errors
- missing version in package.json of npm package
- Failed to publish {} packages:
- Package '{}' not found in catalog
- {} is missing 'version' field
- Export {} not found in the package
AI-assisted analysis of denoland/deno@89f33cbef2 (2026-08-16).
Data as JSON: /api/errors/e10b5419a7547a66.
Report an issue: GitHub.