WhatBroke

Error: Cannot find module after an agent-run npm install

Any AI coding tool Last checked 2026-10-23

Error: Cannot find module means Node resolved require()/import and found nothing on disk — after an agent ran npm install, that almost always means the install happened in the wrong directory, in a sandbox whose filesystem reset before the app ran, or the agent added the import before it ever ran install. Check which node_modules the running process actually sees; do not trust the terminal text that said "added N packages".

What you saw

Error: Cannot find module 'some-package'

The agent's own terminal output clearly showed npm install succeed — added 1 package in 2s, no errors — and the very next command still throws Error: Cannot find module 'some-package' with a Require stack listing your entry file.

npm ls some-package says it is installed, and running node -e "require.resolve('some-package')" from the project root works fine. The app itself still can't find it.

It only fails after a deploy, a container rebuild, or reopening the agent session — it worked a few minutes earlier in the same chat.

In a monorepo it fails only in one workspace package, never at the root, even though the dependency is listed in the root package.json.

The ESM variant looks different: Error [ERR_MODULE_NOT_FOUND]: Cannot find module '/app/src/utils' imported from /app/src/server.js.

What it actually means

Cannot find module is Node reporting that it walked every node_modules directory from the requiring file up to the filesystem root and found nothing. It is a fact about the process running right now — it has no memory of what an earlier npm install command printed.

Agents run shell commands as discrete tool calls, and many agent runtimes do not guarantee tool call N+1 starts in the same working directory tool call N finished in. A common failure: the agent cd'd into packages/api, ran npm install express there, then a later step started the server from the repo root — express is sitting in packages/api/node_modules, which the root process never looks at.

Sandboxed or ephemeral dev environments (cloud agent containers, some CI preview builds, serverless cold starts) can rebuild or reset the filesystem between the install step and the run step. If node_modules is gitignored and the run step starts from a fresh checkout, the install the agent just ran is gone, even though it genuinely succeeded a moment earlier.

Agents frequently add an import/require line in the same edit that introduces a new dependency, then run the app before ever running install — or the install call is buried in a longer chained command (cd api && npm install && npm run build) where an earlier step failed and the shell moved on without actually installing anything.

In npm/yarn/pnpm workspaces, a package installed at the monorepo root is not automatically visible to every workspace package. pnpm's strict node_modules layout in particular refuses to resolve a dependency a package did not declare for itself, even if a sibling package has it.

The ESM ERR_MODULE_NOT_FOUND case is usually a missing explicit file extension or wrong relative path, not a missing package — ESM resolution does not guess .js for you the way CommonJS require does.

The fix

  1. Make the question concrete: which node_modules does the process that is actually failing see? Run this using the app's real start command and real directory, not wherever your own terminal happens to be.

    node -e "console.log(process.cwd()); console.log(require.resolve('some-package'))"
  2. If that throws, find out where the package actually landed on disk.

    find . -maxdepth 4 -type d -name some-package 2>/dev/null
  3. If it's in a subdirectory's node_modules but the app starts elsewhere, that's a monorepo/cwd mismatch, not a missing dependency. Install where the app that imports it actually runs, using workspace flags so the lockfile stays consistent.

    npm install some-package --workspace=packages/api
  4. On pnpm, if only one workspace package fails, that's very likely strict resolution refusing an undeclared dependency. Add it to that package's own package.json and reinstall from the repo root.

    pnpm --filter ./packages/api add some-package
  5. In a sandboxed or cloud container, assume node_modules does not survive a rebuild unless you've proven it does. Re-run install as the literal first command of the run step every time, rather than trusting an earlier step's install is still on disk.

    npm install && npm run dev
  6. If the transcript shows the install never actually ran (chained after a step that failed, or skipped mid-plan), rerun it alone and check the exit code before moving on.

    npm install some-package; echo "exit code: $?"
  7. For the ESM variant importing a local path, the fix is almost always the missing extension, not a reinstall.

    // wrong
    import { helper } from './utils'
    // right
    import { helper } from './utils.js'

How to stop it happening again

Tell the agent, in your rules file or system prompt, to always install with workspace flags (--workspace=, pnpm --filter) rather than a bare cd subdir && npm install, so the dependency lands next to the code that needs it.

After any agent-run install, have it immediately run the app's real start command in the same turn instead of trusting the install's own stdout — a command that printed added N packages can still have installed to the wrong place.

On sandboxed or container-based agent workflows, do not treat node_modules as durable across steps. Put the install at the start of the run command itself (npm install && npm start) so it is self-healing regardless of what the filesystem carried forward.

Never chain npm install behind && in a longer command without checking its own exit code — a failed earlier step silently skips the install and the agent's summary will not flag it.

In any workspace/monorepo, declare a dependency in the package.json of every package that imports it, even if a sibling package already has it. Relying on hoisting works until the project moves to pnpm or npm install --workspaces is run from a different directory.

Related questions

The agent said npm install succeeded. Why is the module still missing?

Because "succeeded" describes the install command's own exit code in whatever directory it ran, not whether the app that later tries to require() the package is looking in that same directory. Agents switch directories between tool calls more often than people switching terminal tabs manually, and that mismatch is the single most common cause of this error after an agent-run install.

Why does it work when I run it myself but fail when the agent runs it?

You likely run the app from the same shell and directory where you last ran install, by habit. An agent's tool calls are not guaranteed to preserve working directory between turns the way your muscle memory does, so it can install in one place and run from another without either command reporting an error.

Is this the same root cause as spawn npx ENOENT?

They're cousins, not the same bug. ENOENT means the launcher binary itself (npx, uv) was not found on PATH before anything ran. Cannot find module means the launcher ran fine, Node started, and it was a specific package or file that could not be resolved. Both are context/environment mismatches rather than problems with your code's logic.

I'm on pnpm and the error only hits one package in my monorepo. Why?

pnpm's default node_modules layout is strict: a package can only resolve dependencies it declares in its own package.json, even if a sibling workspace package already installed the same thing at the root. Add the dependency directly to the failing package's package.json and reinstall from the repo root.

Does reinstalling node_modules from scratch fix it?

It fixes a corrupted or partial install, but not a cwd mismatch or a workspace-declaration problem — you'll just end up with a clean node_modules in the same wrong place. Confirm where the failing process is actually looking (process.cwd() plus require.resolve) before you reach for rm -rf node_modules && npm install.

Other things that break

What Broke This Week

One email, most Thursdays. New symptoms, tool updates that quietly break things, and one fix worth stealing. Unsubscribe in one click.