Cannot find package '<package>' imported from <test-file>
Cannot find package — Vitest ESM module resolution
On this page
What causes this error
Vitest sits on top of Vite’s resolver but tightens it in two ways: tests run in a Node-driven
ESM context (regardless of whether the code under test ships to a browser), and the test
environment (node, jsdom, or happy-dom) gates which globals and DOM APIs are available
during resolution. Four causes account for nearly every report of this error.
First: the package is published as ESM-only with no CommonJS fallback, and Vitest’s optimizer
has not been told to pre-bundle it. Vite handles this in dev because the browser eats ESM
natively, but Vitest’s Node host does not — the fix is to add the package to
test.deps.optimizer.web.include (for browser-targeted code) or
test.deps.optimizer.ssr.include (for server-side code) in vitest.config.ts. Second: the
test environment is node but the imported package assumes a browser — it does
globalThis.window checks at module top-level and crashes when window is undefined. The
remedy is // @vitest-environment jsdom (or happy-dom) at the top of the test file, or a
project-wide test.environment: 'jsdom'. Third: a monorepo workspace package is published
to node_modules via pnpm install but its package.json exports field has a
"types" entry pointing at a file that has not been built — pnpm -r build rebuilds the
graph. Fourth: the package is installed but in the wrong workspace root — pnpm’s hoisting
rules can place it where the test consumer cannot see it; pnpm why <package> reveals the
graph.
How to fix it manually
Run pnpm exec vitest run --reporter=verbose and read the full stack — Vitest prints both
the failing test file and the import path. Run pnpm why <package> to confirm the package
is installed at all and to which workspace. Open vitest.config.ts and add the package to
test.deps.optimizer.<target>.include if it is ESM-only. If the package is browser-coded,
flip the test environment to jsdom. For monorepo cases, run pnpm -r --filter <consumer>... build.
Copy this prompt into your AI coding agent
# Goal
Fix this Vitest "Cannot find package" error using the smallest safe change.
Diagnose which of four causes applies (ESM-only / wrong test environment /
monorepo unbuilt / pnpm hoisting) before patching.
# Context
The Vitest output:
<paste the full vitest run output including the failing test file and the import path>
The vitest.config.ts test.environment value: <node | jsdom | happy-dom>
The package at issue: <package name>
The pnpm why <package> output (run this first):
<paste the pnpm why output here>
# In-scope
- vitest.config.ts test.deps.optimizer entries
- vitest.config.ts test.environment
- The single failing test file and its imports
- package.json workspace declarations if applicable
# Out-of-scope
- Rewriting the package's exports field
- Switching from Vitest to another test runner
- Restructuring the monorepo
- Adding new test runners or environments globally without justification
# Verification
Run `pnpm exec vitest run <failing-test-file>` and confirm exit code 0.
Run `pnpm exec vitest run` (full suite) and confirm no other tests regressed.
Run `pnpm build` and confirm the production build still works.
# Output format
1. One sentence: which of the four causes this is.
2. The diff (only changed files).
3. The verification command output, last 10 lines. Why this prompt works
Forcing the agent to paste the pnpm why <package> output before proposing a fix catches the
hoisting case immediately — pnpm why answers the “is it installed at all” question that
matches one of four causes to the right fix. Listing test.deps.optimizer and
test.environment in In-scope blocks the common Claude Code anti-pattern of suggesting a
new test runner when the existing one is fine. Naming the failing file specifically in the
verification command keeps the fix scope narrow — the full suite confirms nothing regressed
but the targeted run confirms the targeted fix.
Variants by symptom
| Symptom | Diagnostic command |
|---|---|
| Package is ESM-only | Add to test.deps.optimizer.web.include |
window is not defined at module load | Set test.environment: 'jsdom' |
| Monorepo workspace consumer fails | pnpm -r --filter <consumer>... build |
pnpm why shows package in wrong workspace | Move dep to consumer’s package.json |
| Works locally, fails in CI | pnpm install --frozen-lockfile (lockfile drift) |
Related errors and tools
Frequently asked questions
Why does Vitest fail to resolve a package that works in the app?
Vitest runs tests in a Node ESM host. An ESM-only package must be added to the test.deps.optimizer include list, or the test environment switched to jsdom if the package assumes a browser.
When should I set test.environment to jsdom?
Set it when the package touches window or document at module load and the default node environment has no DOM for it to read.
Generate a fix prompt
Build a tailored AI fix prompt for this error.