vitest-dev/vitest · error · Error

Project name "${name}" from "${entryFile}" is not unique. Th

Error message

Project name "${name}" from "${entryFile}" is not unique. The project is already defined by "${existingFile}". All projects should have unique names. Make sure your configuration is correct.

What it means

The detailed duplicate-name error for file-based project resolution. When two resolved entries share a name and there are multiple config files, Vitest reports the declaring file (entryFile) and the file that first claimed the name (existingFile), plus the list of matched config files, so the user can locate both declarations.

Source

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

      // 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)
              .map(e => ` - ${relative(globalConfig.root, e.viteConfig.configFile as string)}`)
              .join('\n'),
            '\n\n',
          ].join('')
        : ' '
      throw new Error([
        `Project name "${name}"`,
        entryFile ? ` from "${entryFile}"` : '',
        ' is not unique.',
        existingFile ? ` The project is already defined by "${existingFile}".` : '',
        filesError,
        'All projects should have unique names. Make sure your configuration is correct.',
      ].join(''))
    }
    seenNames.set(name, entry)
  }
  const seenNamesSet = new Set(seenNames.keys())

  // Browser instance expansion (per-entry config injection).
  const afterBrowser = expandBrowserInstancesInEntries(globalConfig, baseEntries, seenNamesSet)

  // Benchmark expansion (per-entry config injection, runs over post-browser list).
  // `--benchmark` makes every project run as a benchmark.
  const afterBenchmark = expandBenchmarksInEntries(afterBrowser, seenNamesSet, !!globalConfig.cliOptions.benchmarkOnly)

View on GitHub (pinned to 1fa9837ec2)

Solutions

  1. Rename one of the projects so each config file declares a unique name.
  2. Read the listed config files in the error to find both declarations.
  3. If using globs, ensure each matched config sets a distinct, derived name.
  4. Centralize naming (e.g. derive from directory) to avoid manual collisions.

Example fix

// before - packages/a/vitest.config.ts and packages/b/vitest.config.ts both: test: { name: 'core' }
// after - packages/b
export default defineConfig({ test: { name: 'b-core' } })
Defensive patterns

Strategy: validation

Validate before calling

// Scan config files for duplicate project names before running.
import { globSync } from 'glob'
function findDuplicateProjectNames(configFiles: string[]) {
  const seen = new Map<string, string>()
  for (const f of configFiles) {
  const mod = require(f)
  const name = mod?.default?.test?.name
  if (!name) continue
  if (seen.has(name)) throw new Error(`Duplicate project name "${name}" in ${f} (already in ${seen.get(name)})`)
  seen.set(name, f)
  }
}

Type guard

const allProjectNamesUnique = (entries: { name: string; file?: string }[]): boolean =>
  new Set(entries.map(e => e.name)).size === entries.length

Prevention

When it happens

Trigger: Two non-inline project entries (from different config files) resolve to the same name; baseEntries.length > 1 and at least one has a configFile, producing the file list.

Common situations: A glob/workspace matching multiple config files that each define a project with the same name, copy-pasted project configs, or a monorepo where packages reuse a shared name.

Related errors


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