vitest lastVerified: 2026-05-08

Cannot find package '<package>' imported from <test-file>

Cannot find package — Vitest ESM module resolution

On this page
  1. What causes this error
  2. How to fix it manually
  3. Copy this prompt into your AI coding agent
  4. Why this prompt works
  5. Variants by symptom
  6. Related errors and tools

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

vitest-cannot-find-package-fix-prompt.md
# 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

SymptomDiagnostic command
Package is ESM-onlyAdd to test.deps.optimizer.web.include
window is not defined at module loadSet test.environment: 'jsdom'
Monorepo workspace consumer failspnpm -r --filter <consumer>... build
pnpm why shows package in wrong workspaceMove dep to consumer’s package.json
Works locally, fails in CIpnpm install --frozen-lockfile (lockfile drift)

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.