{"id":"31c54bfbaace443e","repo":"vitest-dev/vitest","slug":"cannot-define-a-nested-project-for-a-browser-br","errorCode":null,"errorMessage":"Cannot define a nested project for a ${browser} browser. The project name \"${name}\" was already defined. If you have multiple instances for the same browser, make sure to define a custom \"name\". All projects should have unique names. Make sure your configuration is correct.","messagePattern":"Cannot define a nested project for a (.+?) browser\\. The project name \"(.+?)\" was already defined\\. If you have multiple instances for the same browser, make sure to define a custom \"name\"\\. All projects should have unique names\\. Make sure your configuration is correct\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/vitest/src/node/projects/resolveProjects.ts","lineNumber":750,"sourceCode":"            `@vitest/coverage-v8 does not work with\\n${browserConfig}\\n`\n            + `\\nUse either:\\n${correctExample}`\n            + `\\n\\n...or change your coverage provider to:\\n${coverageExample}\\n`,\n          )\n        }\n\n        if (globalConfig.inspect || globalConfig.inspectBrk) {\n          const inspectOption = `--inspect${globalConfig.inspectBrk ? '-brk' : ''}`\n\n          throw new Error(\n            `${inspectOption} does not work with\\n${browserConfig}\\n`\n            + `\\nUse either:\\n${correctExample}`\n            + `\\n\\n...or disable ${inspectOption}\\n`,\n          )\n        }\n      }\n\n      if (names.has(name)) {\n        throw new Error(\n          [\n            `Cannot define a nested project for a ${browser} browser. The project name \"${name}\" was already defined. `,\n            'If you have multiple instances for the same browser, make sure to define a custom \"name\". ',\n            'All projects should have unique names. Make sure your configuration is correct.',\n          ].join(''),\n        )\n      }\n      names.add(name)\n\n      const clonedConfig = cloneProjectConfigForBrowserInstance(projectConfig, instance)\n      clonedConfig.name = name\n\n      result.push({\n        viteConfig, // shared with parent\n        projectConfig: clonedConfig,\n        ancestors: entry.ancestors,\n      })\n    })","sourceCodeStart":732,"sourceCodeEnd":768,"githubUrl":"https://github.com/vitest-dev/vitest/blob/d568f8ce3739b532d5bf2c1ee1e45e8a8a473d09/packages/vitest/src/node/projects/resolveProjects.ts#L732-L768","documentation":"During browser-instance expansion (resolveProjects.ts:749-757), each instance becomes its own project and its name is added to a `names` set. If two instances produce the same name (e.g. two chromium instances without custom names), the second throws. The message tells you to give each instance a custom `name` when running multiple instances of the same browser engine.","triggerScenarios":"browser.instances contains two entries with the same browser engine and no distinguishing `name` (both fall back to the engine name); instances with explicitly identical `name` fields.","commonSituations":"Wanting to run chromium twice with different viewports/options but forgetting to name them; copy-pasting an instance; defaulting instances from an array of options that omits name.","solutions":["Give every instance a unique `name`: { browser: 'chromium', name: 'chromium-mobile' }, { browser: 'chromium', name: 'chromium-desktop' }.","If you only need one instance per engine, remove the duplicate.","Generate names programmatically from the options (e.g. viewport) when building the instances array."],"exampleFix":"// before\ntest: { browser: { enabled: true, provider: 'playwright', instances: [\n  { browser: 'chromium', viewport: { width: 375, height: 667 } },\n  { browser: 'chromium', viewport: { width: 1280, height: 720 } },\n] } }\n\n// after\ntest: { browser: { enabled: true, provider: 'playwright', instances: [\n  { browser: 'chromium', name: 'mobile', viewport: { width: 375, height: 667 } },\n  { browser: 'chromium', name: 'desktop', viewport: { width: 1280, height: 720 } },\n] } }","handlingStrategy":"validation","validationCode":"const instanceNames = instances.map(i => i.name ?? i.browser)\nconst dupes = instanceNames.filter((n, i) => instanceNames.indexOf(n) !== i)\nif (dupes.length) throw new Error(`Duplicate browser instance names: ${[...new Set(dupes)].join(', ')}`)","typeGuard":"function uniqueInstanceNames(instances: { name?: string; browser: string }[]): boolean {\n  const names = instances.map(i => i.name ?? i.browser)\n  return new Set(names).size === names.length\n}","tryCatchPattern":null,"preventionTips":["Give every instance an explicit `name`, especially when repeating an engine.","Derive names from distinguishing options (viewport, locale) when generating instances.","Run one instance per engine unless you really need multiples."],"tags":["browser","instances","naming","duplicate","configuration"],"analyzedSha":"d568f8ce3739b532d5bf2c1ee1e45e8a8a473d09","analyzedAt":"2026-08-03T20:23:56.861Z","schemaVersion":2}