Describe the bug
In an npm workspaces monorepo, page, userEvent, and server are not exported from vitest/browser when typechecking with tsc. The issue is a TypeScript module resolution failure: vitest/browser/context.d.ts re-exports from @vitest/browser-playwright/context, but when vitest is hoisted to the root node_modules/ and @vitest/browser-playwright is installed only in a workspace's local node_modules/,
TypeScript cannot resolve that re-export from vitest's location. The // @ts-ignore comment above the export silently swallows the resolution failure, so instead of an error on the library file, all the exports from @vitest/browser-playwright/context simply disappear — and user code gets Module '"vitest/browser"' has no exported member 'page'.
This is the expected npm layout for optional peer dependencies: npm deliberately does not hoist @vitest/browser-playwright to root (where vitest lives) because it was not explicitly requested there. The bug is that vitest's type declarations depend on being able to reach their optional peer packages at type-check time, which breaks in any monorepo where those peers are co-located with the workspace rather than
with vitest itself.
The bug only triggers when npm produces this split layout. If npm happens to co-locate vitest and @vitest/browser-playwright in the same node_modules/ directory (for example because a version mismatch forces a local copy of vitest into the workspace), TypeScript can resolve the chain and the error disappears. This makes the bug sensitive to npm hoisting decisions, which can change across installs as dependency versions are bumped.
Reproduction
https://github.com/julienw/vitest-types-issue
git clone https://github.com/julienw/vitest-types-issue
npm ci
cd packages/frontend
npx tsc
I get these errors:
../../node_modules/vitest/dist/browser.d.ts:34:13 - error TS2304: Cannot find name 'BufferEncoding'.
34 encoding?: BufferEncoding;
~~~~~~~~~~~~~~
../../node_modules/vitest/dist/browser.d.ts:38:37 - error TS2304: Cannot find name 'BufferEncoding'.
38 readFile: (path: string, options?: BufferEncoding | FsOptions) => Promise<string>;
~~~~~~~~~~~~~~
../../node_modules/vitest/dist/browser.d.ts:39:55 - error TS2304: Cannot find name 'BufferEncoding'.
39 writeFile: (path: string, content: string, options?: BufferEncoding | (FsOptions & {
~~~~~~~~~~~~~~
test/example.test.ts:2:10 - error TS2305: Module '"vitest/browser"' has no exported member 'page'.
2 import { page, userEvent, server } from "vitest/browser";
~~~~
test/example.test.ts:2:16 - error TS2305: Module '"vitest/browser"' has no exported member 'userEvent'.
2 import { page, userEvent, server } from "vitest/browser";
~~~~~~~~~
test/example.test.ts:2:27 - error TS2305: Module '"vitest/browser"' has no exported member 'server'.
2 import { page, userEvent, server } from "vitest/browser";
~~~~~~
Found 6 errors in 2 files.
Errors Files
3 ../../node_modules/vitest/dist/browser.d.ts:34
3 test/example.test.ts:2
(BufferEncoding errors are a separate issue, already suppressed by skipLibCheck: true in most projects.)
System Info
System:
OS: Linux 6.12 Debian GNU/Linux 13 (trixie) 13 (trixie)
CPU: (16) x64 11th Gen Intel(R) Core(TM) i9-11900H @ 2.50GHz
Memory: 48.89 GB / 62.53 GB
Container: Yes
Shell: 5.2.37 - /bin/bash
Binaries:
Node: 24.15.0 - /home/julien/.nvm/versions/node/v24.15.0/bin/node
Yarn: 1.22.22 - /usr/bin/yarn
npm: 11.12.1 - /home/julien/.nvm/versions/node/v24.15.0/bin/npm
pnpm: 10.9.0 - /home/julien/.local/share/pnpm/pnpm
bun: 1.0.29 - /home/julien/.bun/bin/bun
Deno: 2.0.0 - /home/julien/.cargo/bin/deno
Browsers:
Chrome: 147.0.7727.137
Chromium: 147.0.7727.116
Firefox: 140.10.0esr
Firefox Developer Edition: 140.10.0esr
npmPackages:
@vitest/browser-playwright: 4.1.5 => 4.1.5
(the command doesn't give the version for `vitest` in monorepos, but it's 4.1.5)
Used Package Manager
npm
Validations
Describe the bug
In an npm workspaces monorepo,
page,userEvent, andserverare not exported fromvitest/browserwhen typechecking withtsc. The issue is a TypeScript module resolution failure:vitest/browser/context.d.tsre-exports from@vitest/browser-playwright/context, but whenvitestis hoisted to the rootnode_modules/and@vitest/browser-playwrightis installed only in a workspace's localnode_modules/,TypeScript cannot resolve that re-export from
vitest's location. The// @ts-ignorecomment above the export silently swallows the resolution failure, so instead of an error on the library file, all the exports from@vitest/browser-playwright/contextsimply disappear — and user code getsModule '"vitest/browser"' has no exported member 'page'.This is the expected npm layout for optional peer dependencies: npm deliberately does not hoist
@vitest/browser-playwrightto root (wherevitestlives) because it was not explicitly requested there. The bug is thatvitest's type declarations depend on being able to reach their optional peer packages at type-check time, which breaks in any monorepo where those peers are co-located with the workspace rather thanwith
vitestitself.The bug only triggers when npm produces this split layout. If npm happens to co-locate
vitestand@vitest/browser-playwrightin the samenode_modules/directory (for example because a version mismatch forces a local copy ofvitestinto the workspace), TypeScript can resolve the chain and the error disappears. This makes the bug sensitive to npm hoisting decisions, which can change across installs as dependency versions are bumped.Reproduction
https://github.com/julienw/vitest-types-issue
I get these errors:
(
BufferEncodingerrors are a separate issue, already suppressed byskipLibCheck: truein most projects.)System Info
System: OS: Linux 6.12 Debian GNU/Linux 13 (trixie) 13 (trixie) CPU: (16) x64 11th Gen Intel(R) Core(TM) i9-11900H @ 2.50GHz Memory: 48.89 GB / 62.53 GB Container: Yes Shell: 5.2.37 - /bin/bash Binaries: Node: 24.15.0 - /home/julien/.nvm/versions/node/v24.15.0/bin/node Yarn: 1.22.22 - /usr/bin/yarn npm: 11.12.1 - /home/julien/.nvm/versions/node/v24.15.0/bin/npm pnpm: 10.9.0 - /home/julien/.local/share/pnpm/pnpm bun: 1.0.29 - /home/julien/.bun/bin/bun Deno: 2.0.0 - /home/julien/.cargo/bin/deno Browsers: Chrome: 147.0.7727.137 Chromium: 147.0.7727.116 Firefox: 140.10.0esr Firefox Developer Edition: 140.10.0esr npmPackages: @vitest/browser-playwright: 4.1.5 => 4.1.5 (the command doesn't give the version for `vitest` in monorepos, but it's 4.1.5)Used Package Manager
npm
Validations