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 dependencies

View on GitHub (pinned to 89f33cbef2)

Solutions

  1. Add the npm package as a workspace member whose package.json `"name"` exactly matches the imported package name
  2. If the package was renamed, update the imports to the new name
  3. 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

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


AI-assisted analysis of denoland/deno@89f33cbef2 (2026-08-16). Data as JSON: /api/errors/e10b5419a7547a66. Report an issue: GitHub.