vitest-dev/vitest · error · Error
vitest/browser can be imported only inside the Browser Mode.
Error message
vitest/browser can be imported only inside the Browser Mode. Instead, it was imported outside of Vitest.
What it means
Same virtual-module guard as the pool variant, but here `globalThis.__vitest_worker__` is undefined or has no ctx.pool — meaning the module is being imported outside any vitest worker at all (no test runner present). The fallback throws telling you the import happened outside vitest entirely.
Source
Thrown at packages/browser/context.js:14
// Vitest resolves "vitest/browser" as a virtual module instead
// fake exports for static analysis
export const page = null
export const server = null
export const userEvent = null
export const cdp = null
export const commands = null
export const locators = null
export const utils = null
const pool = globalThis.__vitest_worker__?.ctx?.pool
throw new Error(
// eslint-disable-next-line prefer-template
'vitest/browser can be imported only inside the Browser Mode. '
+ (pool
? `Your test is running in ${pool} pool. Make sure your regular tests are excluded from the "test.include" glob pattern.`
: 'Instead, it was imported outside of Vitest.'),
)
View on GitHub (pinned to 1fa9837ec2)
Solutions
- Run the file under vitest with the browser pool instead of node/tsx/vite directly.
- Mark `vitest/browser` as external in build/eslint configs that should not evaluate it.
- Move shared helpers out of files that import `vitest/browser` so non-vitest tooling does not pull it in.
- Use a dynamic import gated on a vitest-only environment check for code shared with non-vitest contexts.
Example fix
// before
// utils.shared.ts imported by both vitest browser tests and a node script
import { page } from 'vitest/browser' // throws when node script runs
// after
// keep the vitest/browser import inside test-only files; shared utils take page as a parameter
export function fillForm(p: Page) { /* ... */ }
// test file (vitest only):
import { page } from 'vitest/browser'
fillForm(page) Defensive patterns
Strategy: type-guard
Validate before calling
// before importing vitest/browser in shared code, ensure a vitest worker exists const inVitest = typeof globalThis.__vitest_worker__ !== 'undefined' const inBrowserPool = globalThis.__vitest_worker__?.ctx?.pool === 'browser' // only dynamic-import when both are true
Type guard
function isVitestBrowserWorker(): boolean {
return globalThis.__vitest_worker__?.ctx?.pool === 'browser'
} Prevention
- Keep vitest/browser imports out of files loaded by non-vitest tooling.
- Mark vitest/browser as external in eslint/build configs that should not resolve it.
- Inject browser-only dependencies via dynamic import gated on a worker check.
When it happens
Trigger: Running the file with plain node/tsx/vite outside vitest; importing a browser test module from a script, a Storybook story, an ESLint rule, a build step, or a non-vitest test runner (jest).
Common situations: Tooling that statically evaluates or imports test files (eslint import/no-unresolved, storybook, typecheck scripts, unit tests in another framework); a dev script that loads test utilities; SSR/build accidentally bundling the browser module.
Related errors
- vitest/browser can be imported only inside the Browser Mode.
- The ${provider.name} provider does not support tracing.
- You've enabled headless mode for "preview" provider but it d
- Failed to import test file ${filepath}
- Not called in the browser
AI-assisted analysis of vitest-dev/vitest@1fa9837ec2 (2026-08-11).
Data as JSON: /api/errors/d82dbb6e298aa262.
Report an issue: GitHub.