Skip to main content
On this page

deno why

The deno why command explains why a particular package is in your dependency tree by printing every path from your project's direct dependencies down to the queried package. It reads the lockfile, so it works regardless of which node_modules / npm resolver mode you use and without touching the network.

It pairs with deno add and deno remove: once you know why a transitive dependency is in your tree, you can decide whether to remove a direct dependency that's pulling it in.

Usage Jump to heading

>_
deno why <package>

<package> is an npm or JSR package name, optionally pinned with @<version>:

Form Meaning
ms every version of ms in the tree
ms@2.0.0 only the 2.0.0 version
@std/path a JSR package by its bare name
jsr:@std/path a JSR package by its full specifier
npm:express force npm lookup (useful when names collide)

Examples Jump to heading

Multiple paths to a single package Jump to heading

>_
$ deno why ms
ms@2.0.0
  npm:express@^4.18.0 > debug@2.6.9 > ms@2.0.0
  npm:express@^4.18.0 > body-parser@1.20.4 > debug@2.6.9 > ms@2.0.0
  npm:express@^4.18.0 > finalhandler@1.3.2 > debug@2.6.9 > ms@2.0.0

ms@2.1.3
  npm:express@^4.18.0 > send@0.19.2 > ms@2.1.3

When the same package appears at multiple versions, each is shown in its own block — handy for diagnosing duplicated dependencies that bloat node_modules.

Pinned to a single version Jump to heading

>_
$ deno why ms@2.1.3
ms@2.1.3
  npm:express@^4.18.0 > send@0.19.2 > ms@2.1.3

JSR packages Jump to heading

>_
$ deno why @std/path
@std/path@1.0.6
  @scope/my-lib@^1.0.0 > @std/path@1.0.6
  @std/fs@^1.0.16 > @std/path@1.0.6

JSR packages added in Deno 2.8+ resolve the same way npm packages do — you can pass either the bare name (@std/path) or the full specifier (jsr:@std/path).

Workspace members Jump to heading

In a workspace, each member's direct dependencies appear as roots in the output, so a transitive dep introduced by one package is clearly attributable to that package.

Exit codes Jump to heading

Exit code Meaning
0 The package was found in the resolved tree — at least one dependency path was printed.
Non-zero The package is not in the resolved tree, or the argument is malformed.

The non-zero exit is the easy way to gate CI on a package not being pulled in. For example, to assert that left-pad never enters your tree:

>_
# fails the build if left-pad is reachable
! deno why left-pad

Common pitfalls Jump to heading

  • "Package not found" but you know it's used at runtime. deno why reports what's in the lockfile, not what's imported by your code. If you've added a npm: or jsr: specifier but haven't run deno install (or any subcommand that resolves), the package won't appear yet.
  • Resolution depends on workspace mode. A package only consumed by one workspace member may not show up when run from a different member's directory if your workspace setup uses per-member lockfiles. Run deno why from the workspace root for the complete picture.
Command line usage:
deno why [OPTIONS] <package>

Show why a package is installed, displaying the dependency chain from your project's direct dependencies to the specified package.

deno why express

Show why a specific version is installed

deno why express@4.18.2

Dependency management options Jump to heading

--frozen<BOOLEAN>optional
Jump to heading

Error out if lockfile is out of date.

--lock<FILE>optional
Jump to heading

Check the specified lock file. (If value is not provided, defaults to "./deno.lock").

Disable auto discovery of the lock file.

Last updated on

Did you find what you needed?

Privacy policy