jestjs/jest · error · Error

Whoops! Two projects resolved to the same config path: ${Str

Error message

Whoops! Two projects resolved to the same config path: ${String(configPath)}:

  Project 1: ${projects[parsedConfigs.indexOf(config)]}
  Project 2: ${projects[parsedConfigs.indexOf(configPathMap.get(configPath))]}

This usually means that your "projects" config includes a directory that doesn't have any configuration recognizable by Jest. Please fix it.

What it means

When resolving a multi-project config, `readConfigs` calls `ensureNoDuplicateConfigs` (packages/jest-config/src/index.ts:268), which throws if two project entries resolve to the SAME config file path. This typically happens when a `projects` entry is a directory without its own jest.config.* — Jest walks up and falls back to the parent/root config, so multiple such directories collapse onto one config path.

Source

Thrown at packages/jest-config/src/index.ts:296

  for (const config of parsedConfigs) {
    const {configPath} = config;

    if (configPathMap.has(configPath)) {
      const message = `Whoops! Two projects resolved to the same config path: ${chalk.bold(
        String(configPath),
      )}:

  Project 1: ${chalk.bold(projects[parsedConfigs.indexOf(config)])}
  Project 2: ${chalk.bold(
    projects[parsedConfigs.indexOf(configPathMap.get(configPath))],
  )}

This usually means that your ${chalk.bold(
        '"projects"',
      )} config includes a directory that doesn't have any configuration recognizable by Jest. Please fix it.
`;

      throw new Error(message);
    }
    if (configPath !== null) {
      configPathMap.set(configPath, config);
    }
  }
};

export interface ReadJestConfigOptions {
  /**
   * The package root or deserialized config (default is cwd)
   */
  packageRootOrConfig?: string | Config.InitialOptions;
  /**
   * When the `packageRootOrConfig` contains config, this parameter should
   * contain the dirname of the parent config
   */
  parentConfigDirname?: null | string;
  /**

View on GitHub (pinned to f49721c78e)

Solutions

  1. Give each project its own jest.config.{js,ts,...} so the resolved config paths differ.
  2. If the projects genuinely share one config, list that config once instead of listing multiple bare directories.
  3. Remove duplicate/overlapping entries from the `projects` array (check globs and symlinks).

Example fix

// before (root jest.config.js)
module.exports = { projects: ['packages/a', 'packages/b'] }; // a & b have no config

// after: give each package its own jest.config.js, or collapse to a single root config
module.exports = { testEnvironment: 'node' };
Defensive patterns

Strategy: validation

Validate before calling

import * as path from 'node:path';
import * as fs from 'node:fs';
import {constants} from 'jest-config';
function assertDistinctProjectConfigs(roots: string[]): void {
  const seen = new Set<string>();
  for (const root of roots) {
    const resolved = resolveProjectConfigPath(root);
    if (seen.has(resolved)) throw new Error(`Duplicate resolved config path: ${resolved} (from ${root})`);
    seen.add(resolved);
  }
}
// resolveProjectConfigPath: find jest.config.* in root or walk up

Type guard

const isUniqueConfigPaths = (paths: string[]) => new Set(paths).size === paths.length;

Prevention

When it happens

Trigger: `projects: ['packages/a', 'packages/b']` where neither a nor b has a jest.config.* file (both resolve to the repo-root jest.config.js); or two project globs that overlap.

Common situations: Monorepos where some packages lack per-package config; renaming/removing a package's jest.config.js; glob expansion producing duplicate or nested paths.

Related errors


AI-assisted analysis of jestjs/jest@f49721c78e (2026-08-03). Data as JSON: /data/errors/fba3e0ae6f23fe4d.json. Report an issue: GitHub.