vitest-dev/vitest · critical · Error
Browser provider is not defined for the project
Error message
Browser provider is not defined for the project "${child.project.name}". This is a bug in Vitest. Please, open a new issue with a reproduction. What it means
pluginContext builds the cached browser-runner context module that is shared across a project's instances. It reads the provider name from the resolved config (child.config.browser.provider?.name) rather than the lazily-initialized provider instance. If that config field is absent, the framework considers it an internal invariant violation and asks the user to file a bug, because the config resolution layer should always populate provider.name before this code runs.
Solutions
- Verify you are on a released, mutually-compatible version of vitest and @vitest/browser (no version skew after a partial upgrade).
- Check that browser.provider is a known string ('playwright' | 'webdriverio' | 'preview') in your config, not a hand-rolled object.
- Reinstall node_modules to rule out a partially-linked monorepo build.
- If the issue reproduces on a clean install, file the bug report the error asks for, including vitest version, provider, and a minimal reproduction.
Example fix
// before - hand-rolled provider object, no name resolved
browser: { provider: { name: undefined } as any }
// after - use a known provider string and let Vitest resolve it
browser: { provider: 'playwright' } Defensive patterns
Strategy: validation
Validate before calling
function hasResolvedProvider(cfg: { browser?: { provider?: { name?: string } | string } }): boolean {
const p = cfg.browser?.provider
return typeof p === 'string' ? p.length > 0 : !!p && typeof p.name === 'string' && p.name.length > 0
} Type guard
function isKnownProviderName(name: unknown): name is 'playwright' | 'webdriverio' | 'preview' {
return name === 'playwright' || name === 'webdriverio' || name === 'preview'
} Prevention
- Pin mutually-compatible versions of vitest and @vitest/browser.
- Always specify browser.provider as a known string, never a hand-rolled object.
- Reinstall node_modules after partial upgrades to clear stale links.
When it happens
Trigger: Reaching pluginContext with a project whose config.browser.provider object exists but has no `name` field, or where config resolution was bypassed (e.g. a custom Vitest integration that constructs TestProject manually). The code path is hit when the orchestrator tester module is first requested by the browser.
Common situations: A regression in config resolution after upgrading Vitest; a third-party plugin that mutates config.browser.provider after resolution; running a canary/linked build of @vitest/browser where resolveConfig did not run; an edge case with a custom provider object literal missing the name property.
Related errors
- Browser name is required. Please, set…
- All browser instances within a project must use the same…
- "browser.instances" was set in the config, but the array is…
- browser is not initialized
- Browser Mode requires the "provider" to always be specified.
AI-assisted analysis of vitest-dev/vitest@1fa9837ec2 (2026-08-11).
Data as JSON: /api/errors/64e7976b17ddbade.
Report an issue: GitHub.
Appendix: source
Thrown at packages/browser/src/node/plugins/pluginContext.ts:50
}
}
async function generateContextFile(
this: Rollup.PluginContext,
globalServer: ParentBrowserProject,
) {
const commands = Object.keys(globalServer.commands)
// The provider instance is initialized lazily when a page opens, so reading
// `child.provider` here races and can be `undefined` before the first page is
// opened. The provider name is uniform across a project's instances and is
// already resolved on the config, so read it from there for this shared
// (cached) context module. The instance is still used below for the
// preview-only user-event import.
const child = [...globalServer.children][0]
const provider = child.provider
const providerName = child.config.browser.provider?.name
if (!providerName) {
throw new Error(
`Browser provider is not defined for the project "${child.project.name}". This is a bug in Vitest. Please, open a new issue with a reproduction.`,
)
}
const commandsCode = commands
.filter(command => !command.startsWith('__vitest'))
.map((command) => {
return ` ["${command}"]: (...args) => __vitest_browser_runner__.commands.triggerCommand("${command}", args),`
})
.join('\n')
const userEventNonProviderImport = await getUserEventImport(
provider,
this.resolve.bind(this),
)
const distContextPath = slash(`/@fs/${resolve(__dirname, 'context.js')}`)
return `View on GitHub (pinned to 1fa9837ec2)