vitest-dev/vitest · error · Error

The browser configuration must have a "browser" property…

Error message

The browser configuration must have a "browser" property. The ${nth}${ending} item in "browser.instances" doesn't have it. Make sure your${projectConfig.name ? ` "${projectConfig.name}"` : ''} configuration is correct.

What it means

When expanding browser.instances, each instance must specify a 'browser' field. The loop computes an ordinal label (1st/2nd/3rd/Nth) and names the parent project if it has one, so the user can locate the offending instance entry in their config.

Solutions

  1. Add the 'browser' field (e.g. 'chromium', 'firefox', 'webkit') to the indicated instance.
  2. Use the ordinal in the error to find the exact instance in your config.
  3. Validate every instances entry has a browser string before running.

Example fix

// before
browser: { instances: [{ name: 'chrome' /* no browser */ }] }
// after
browser: { instances: [{ name: 'chrome', browser: 'chromium' }] }
Defensive patterns

Strategy: type-guard

Validate before calling

// Validate browser.instances entries before running.
function validateInstances(instances: { browser?: string; name?: string }[]) {
  instances.forEach((inst, i) => {
  if (!inst.browser) throw new Error(`Instance #${i + 1} is missing required "browser" field`)
  })
}

Type guard

const isCompleteInstance = (inst: unknown): inst is { browser: string; name?: string } =>
  typeof inst === 'object' && inst !== null && typeof (inst as any).browser === 'string'

Prevention

When it happens

Trigger: A browser.instances array entry is missing the 'browser' property (e.g. only specifies name/provider), so instance.browser is falsy at expansion time.

Common situations: Typing 'browserName' instead of 'browser', omitting the field, or a copy-paste from a config that used a different key.

Related errors


AI-assisted analysis of vitest-dev/vitest@1fa9837ec2 (2026-08-11). Data as JSON: /api/errors/c40a96e16d47e7c2. Report an issue: GitHub.

Appendix: source

Thrown at packages/vitest/src/node/projects/resolveProjects.ts:878

      ? instances
      : instances.filter(instance => matchesProjectFilter(globalConfig.project, instance.name!))
    if (!filteredInstances.length) {
      continue
    }

    // Keep the parent in the entry list as `hidden` so a `TestProject` is
    // created (instances link to it via `_parent` for the browser provider).
    // The parent's name is removed from `names` because the instance names
    // take its place in the user-facing project list.
    names.delete(parentName)
    result.push({ ...entry, hidden: true })

    filteredInstances.forEach((instance, index) => {
      const browser = instance.browser
      if (!browser) {
        const nth = index + 1
        const ending = nth === 2 ? 'nd' : nth === 3 ? 'rd' : 'th'
        throw new Error(`The browser configuration must have a "browser" property. The ${nth}${ending} item in "browser.instances" doesn't have it. Make sure your${projectConfig.name ? ` "${projectConfig.name}"` : ''} configuration is correct.`)
      }
      const name = instance.name
      if (name == null) {
        throw new Error(`The browser configuration must have a "name" property. This is a bug in Vitest. Please, open a new issue with reproduction`)
      }
      if (instance.provider?.name != null && projectConfig.browser.provider?.name != null && instance.provider?.name !== projectConfig.browser.provider?.name) {
        throw new Error(`The instance cannot have a different provider from its parent. The "${name}" instance specifies "${instance.provider?.name}" provider, but its parent has a "${projectConfig.browser.provider?.name}" provider.`)
      }

      const provider = instance.provider?.name ?? projectConfig.browser.provider?.name ?? 'preview'

      // Browser-mode CDP only features:
      if (provider === 'preview' || !isChromiumName(provider, browser)) {
        const browserConfig = `
{
  browser: {
    provider: ${provider}(),
    instances: [

View on GitHub (pinned to 1fa9837ec2)