{"id":"c40a96e16d47e7c2","repo":"vitest-dev/vitest","slug":"the-browser-configuration-must-have-a-browser-pr","errorCode":null,"errorMessage":"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.","messagePattern":"The browser configuration must have a \"browser\" property\\. The (.+?)(.+?) item in \"browser\\.instances\" doesn't have it\\. Make sure your(.+?)\"` : ''\\} configuration is correct\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/vitest/src/node/projects/resolveProjects.ts","lineNumber":682,"sourceCode":"      ? instances\n      : instances.filter(instance => matchesProjectFilter(globalConfig.project, instance.name!))\n    if (!filteredInstances.length) {\n      continue\n    }\n\n    // Keep the parent in the entry list as `hidden` so a `TestProject` is\n    // created (instances link to it via `_parent` for the browser provider).\n    // The parent's name is removed from `names` because the instance names\n    // take its place in the user-facing project list.\n    names.delete(parentName)\n    result.push({ ...entry, hidden: true })\n\n    filteredInstances.forEach((instance, index) => {\n      const browser = instance.browser\n      if (!browser) {\n        const nth = index + 1\n        const ending = nth === 2 ? 'nd' : nth === 3 ? 'rd' : 'th'\n        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.`)\n      }\n      const name = instance.name\n      if (name == null) {\n        throw new Error(`The browser configuration must have a \"name\" property. This is a bug in Vitest. Please, open a new issue with reproduction`)\n      }\n      if (instance.provider?.name != null && projectConfig.browser.provider?.name != null && instance.provider?.name !== projectConfig.browser.provider?.name) {\n        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.`)\n      }\n\n      const provider = instance.provider?.name ?? projectConfig.browser.provider?.name ?? 'preview'\n\n      // Browser-mode CDP only features:\n      if (provider === 'preview' || !isChromiumName(provider, browser)) {\n        const browserConfig = `\n{\n  browser: {\n    provider: ${provider}(),\n    instances: [","sourceCodeStart":664,"sourceCodeEnd":700,"githubUrl":"https://github.com/vitest-dev/vitest/blob/d568f8ce3739b532d5bf2c1ee1e45e8a8a473d09/packages/vitest/src/node/projects/resolveProjects.ts#L664-L700","documentation":"During browser-instance expansion (resolveProjects.ts:677-683), each item in browser.instances must specify which browser to launch via a `browser` field. If an instance object omits it, Vitest throws, naming the 1-based ordinal (with st/nd/rd/th suffix) and the parent project name when available.","triggerScenarios":"Defining browser.instances as [{ name: 'chrome' }, { name: 'firefox' }] where each object has a name but no browser field; an instance built dynamically that drops the browser key; copy-pasting an instance template that used a different shape.","commonSituations":"Confusing the `name` (project label) and `browser` (browser engine) fields; upgrading from an older API where browser was inferred; typos like 'broswer'; instances constructed from a map that loses the browser key.","solutions":["Add the `browser` field to every item: { browser: 'chromium', name: 'chromium' }, { browser: 'firefox', name: 'firefox' }.","Double-check the spelling: it's `browser`, not `browserName` or `type`.","Validate your instances array shape with a quick loop before running."],"exampleFix":"// before\ntest: { browser: { enabled: true, provider: 'playwright', instances: [\n  { name: 'chrome' }, { name: 'firefox' },\n] } }\n\n// after\ntest: { browser: { enabled: true, provider: 'playwright', instances: [\n  { browser: 'chromium', name: 'chromium' }, { browser: 'firefox', name: 'firefox' },\n] } }","handlingStrategy":"type-guard","validationCode":"for (const [i, inst] of config.browser.instances.entries()) {\n  if (!inst.browser) throw new Error(`Instance #${i + 1} missing required 'browser' field`)\n}","typeGuard":"function isValidInstance(inst: unknown): inst is { browser: string; name?: string } {\n  return !!inst && typeof inst === 'object' && typeof (inst as any).browser === 'string'\n}","tryCatchPattern":null,"preventionTips":["Always specify `browser` on every instance object.","Validate the instances array shape in a config plugin before running.","Use the same field names as the docs: browser, name, provider, viewport."],"tags":["browser","instances","configuration","validation"],"analyzedSha":"d568f8ce3739b532d5bf2c1ee1e45e8a8a473d09","analyzedAt":"2026-08-03T20:23:56.861Z","schemaVersion":2}