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 whyreports what's in the lockfile, not what's imported by your code. If you've added anpm:orjsr:specifier but haven't rundeno 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 whyfrom the workspace root for the complete picture.
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>optionalError out if lockfile is out of date.
--lock<FILE>optionalCheck the specified lock file. (If value is not provided, defaults to "./deno.lock").
--no-lockDisable auto discovery of the lock file.