vitest-dev/vitest · error · Error

Project name " " is not unique. All projects should have…

Error message

Project name "${name}" is not unique. All projects should have unique names. Make sure your configuration is correct.

What it means

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.

Solutions

  1. Give injected projects unique names distinct from static projects.
  2. Inspect existing workspace project names before injecting and avoid collisions.
  3. If duplication is intentional, reconsider the design - workspace names must be unique.

Example fix

// before
injectTestProjects([{ test: { name: 'unit' } }]) // 'unit' already exists
// after
injectTestProjects([{ test: { name: 'unit-extra' } }])
Defensive patterns

Strategy: validation

Validate before calling

// Before injecting, ensure names are unique vs the active workspace.
function assertUniqueInject(existing: Set<string>, incoming: { name: string }[]) {
  for (const p of incoming) {
  if (existing.has(p.name)) throw new Error(`Injected project name "${p.name}" clashes with an existing project`)
  existing.add(p.name)
  }
}

Type guard

const hasUniqueNames = (existing: Set<string>, incoming: { name: string }[]): boolean =>
  incoming.every(p => !existing.has(p.name))

Prevention

When it happens

Trigger: injectTestProjects (or equivalent runtime injection) supplies a project whose name matches a project already present in the workspace, triggering the existingNames.has(name) branch.

Common situations: A plugin/tool injecting projects at runtime with a name that duplicates a statically-declared project, or two inject calls using the same name.

Related errors


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

Appendix: source

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

        ...(globalConfig._containerConfigFiles || []),
        ...containerConfigFiles,
      ]
    }
  }
  else {
    baseEntries = [{ viteConfig: globalViteConfig, projectConfig: globalConfig }]
  }

  // Ensure project names are unique across declared projects (and any
  // already-existing projects passed via `existingNames`, which the inject
  // path uses to forbid clashes with the active workspace). Include config
  // file paths in the error when available (matches the old workspace-mode
  // duplicate-name diagnostic).
  const seenNames = new Map<string, ResolvedProjectEntry>()
  for (const entry of baseEntries) {
    const name = entry.projectConfig.name
    if (existingNames?.has(name)) {
      throw new Error(
        `Project name "${name}" is not unique. All projects should have unique names. Make sure your configuration is correct.`,
      )
    }
    const existing = seenNames.get(name)
    if (existing) {
      // inline entries carry the configFile they extend, which doesn't say
      // where the project is declared, so they are reported without a file
      const entryFile = !entry.inline && entry.viteConfig.configFile
        ? relative(globalConfig.root, entry.viteConfig.configFile)
        : ''
      const existingFile = !existing.inline && existing.viteConfig.configFile
        ? relative(globalConfig.root, existing.viteConfig.configFile)
        : ''
      const filesError = baseEntries.length > 1 && (entryFile || existingFile)
        ? [
            '\n\nYour config matched these files:\n',
            baseEntries
              .filter(e => !e.inline && e.viteConfig.configFile)

View on GitHub (pinned to 1fa9837ec2)