{"id":"1d46cd3668f7d34b","repo":"vitest-dev/vitest","slug":"project-name-name-is-not-unique-all-projects","errorCode":null,"errorMessage":"Project name \"${name}\" is not unique. All projects should have unique names. Make sure your configuration is correct.","messagePattern":"Project name \"(.+?)\" is not unique\\. 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":146,"sourceCode":"        ...(globalConfig._containerConfigFiles || []),\n        ...containerConfigFiles,\n      ]\n    }\n  }\n  else {\n    baseEntries = [{ viteConfig: globalViteConfig, projectConfig: globalConfig }]\n  }\n\n  // Ensure project names are unique across declared projects (and any\n  // already-existing projects passed via `existingNames`, which the inject\n  // path uses to forbid clashes with the active workspace). Include config\n  // file paths in the error when available (matches the old workspace-mode\n  // duplicate-name diagnostic).\n  const seenNames = new Map<string, ResolvedProjectEntry>()\n  for (const entry of baseEntries) {\n    const name = entry.projectConfig.name\n    if (existingNames?.has(name)) {\n      throw new Error(\n        `Project name \"${name}\" is not unique. All projects should have unique names. Make sure your configuration is correct.`,\n      )\n    }\n    const existing = seenNames.get(name)\n    if (existing) {\n      // inline entries carry the configFile they extend, which doesn't say\n      // where the project is declared, so they are reported without a file\n      const entryFile = !entry.inline && entry.viteConfig.configFile\n        ? relative(globalConfig.root, entry.viteConfig.configFile)\n        : ''\n      const existingFile = !existing.inline && existing.viteConfig.configFile\n        ? relative(globalConfig.root, existing.viteConfig.configFile)\n        : ''\n      const filesError = baseEntries.length > 1 && (entryFile || existingFile)\n        ? [\n            '\\n\\nYour config matched these files:\\n',\n            baseEntries\n              .filter(e => !e.inline && e.viteConfig.configFile)","sourceCodeStart":128,"sourceCodeEnd":164,"githubUrl":"https://github.com/vitest-dev/vitest/blob/d568f8ce3739b532d5bf2c1ee1e45e8a8a473d09/packages/vitest/src/node/projects/resolveProjects.ts#L128-L164","documentation":"Thrown by the runtime inject path (resolveProjects.ts:145-148) when resolveProjectEntries is called with existingNames (the set of already-active project names) and a newly injected project's name collides with one of them. This is the shorter message used when names clash against the live workspace rather than within a single resolution batch.","triggerScenarios":"Calling vitest.injectTestProjects (resolveAndAttachProjects at resolveProjects.ts:1235) with a definition whose test.name matches an already-running project; injecting a project whose auto-resolved name (package.json name or directory basename) matches an existing one.","commonSituations":"A plugin or watch-mode reload injects a project whose name duplicates the original; dynamically adding a project at runtime without checking the active project list; two workspace entries that resolve to the same package.json name.","solutions":["Before injecting, check vitest.projects.map(p => p.name) and pick a unique name.","Set an explicit test.name on the injected config to avoid auto-resolution collisions.","Close or remove the existing project before re-injecting under the same name.","If the duplicate is unintentional, audit your workspace/projects array for two entries resolving to the same name."],"exampleFix":"// before\nawait vitest.injectTestProjects([{ test: { name: 'unit', environment: 'node' } }]) // 'unit' already exists\n\n// after\nconst used = new Set(vitest.projects.map(p => p.name))\nawait vitest.injectTestProjects([{ test: { name: used.has('unit') ? 'unit-2' : 'unit', environment: 'node' } }])","handlingStrategy":"validation","validationCode":"const used = new Set(vitest.projects.map(p => p.name))\nconst candidate = newProjectName\nif (used.has(candidate)) throw new Error(`Name '${candidate}' already in active workspace`)\nawait vitest.injectTestProjects([definition])","typeGuard":"function isUniqueName(name: string, existing: Set<string>): boolean {\n  return !existing.has(name)\n}","tryCatchPattern":null,"preventionTips":["Before injectTestProjects, diff candidate names against vitest.projects.","Set explicit test.name on injected projects rather than relying on auto-resolution.","Close the old project before re-injecting under the same name."],"tags":["projects","naming","inject","duplicate","configuration"],"analyzedSha":"d568f8ce3739b532d5bf2c1ee1e45e8a8a473d09","analyzedAt":"2026-08-03T20:23:56.861Z","schemaVersion":2}