{"record":{"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":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/vitest/src/node/projects/resolveProjects.ts","lineNumber":149,"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":131,"sourceCodeEnd":167,"githubUrl":"https://github.com/vitest-dev/vitest/blob/1fa9837ec26533512fdcad8baebf249771bd340a/packages/vitest/src/node/projects/resolveProjects.ts#L131-L167","documentation":"During project resolution, each project name is checked against existingNames (names already in the active workspace, used by the runtime inject path) and a local seenNames map. If a new entry's name collides with an existing workspace name, resolution aborts. This is the inject-path variant without file context.","triggerScenarios":"injectTestProjects (or equivalent runtime injection) supplies a project whose name matches a project already present in the workspace, triggering the existingNames.has(name) branch.","commonSituations":"A plugin/tool injecting projects at runtime with a name that duplicates a statically-declared project, or two inject calls using the same name.","solutions":["Give injected projects unique names distinct from static projects.","Inspect existing workspace project names before injecting and avoid collisions.","If duplication is intentional, reconsider the design - workspace names must be unique."],"exampleFix":"// before\ninjectTestProjects([{ test: { name: 'unit' } }]) // 'unit' already exists\n// after\ninjectTestProjects([{ test: { name: 'unit-extra' } }])","handlingStrategy":"validation","validationCode":"// Before injecting, ensure names are unique vs the active workspace.\nfunction assertUniqueInject(existing: Set<string>, incoming: { name: string }[]) {\n  for (const p of incoming) {\n  if (existing.has(p.name)) throw new Error(`Injected project name \"${p.name}\" clashes with an existing project`)\n  existing.add(p.name)\n  }\n}","typeGuard":"const hasUniqueNames = (existing: Set<string>, incoming: { name: string }[]): boolean =>\n  incoming.every(p => !existing.has(p.name))","tryCatchPattern":null,"preventionTips":["Namespace injected project names to avoid clashing with static projects.","Maintain a registry of declared names when injecting at runtime.","Document reserved names for static projects."],"tags":["projects","config","naming","inject"],"backgroundTag":null,"analyzedSha":"1fa9837ec26533512fdcad8baebf249771bd340a","analyzedAt":"2026-08-11T16:11:39.638Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}