jestjs/jest · error · Error
Whoops! Two projects resolved to the same config path
Error 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.
What it means
ensureNoDuplicateConfigs (index.ts:268-302) walks each parsed project in a multi-project setup and records its resolved configPath; if two projects map to the same path, it throws. This typically happens when a projects entry is a directory with no Jest-recognizable config, so Jest falls back to resolving the SAME parent config for both — collapsing what you intended as distinct projects into one.
Solutions
- Ensure each project directory listed in projects has its own jest.config.{js,ts,...} or a package.json with a jest key.
- Give each project a unique displayName so they are distinguishable.
- Check the two project paths reported in the message — the duplicate usually means one of them has no config and is inheriting the root.
- If a directory should share the root config intentionally, remove it from the projects array (the root already covers it).
Example fix
// before (packages/b has no jest.config)
module.exports = { projects: ['packages/a', 'packages/b'] };
// after
// add packages/b/jest.config.js with at least module.exports = { displayName: 'b' }; Defensive patterns
Strategy: validation
Validate before calling
import * as fs from 'node:fs';
import * as path from 'node:path';
const EXTS = ['.js','.ts','.mjs','.cjs','.json','.mts','.cts'];
function assertEachProjectHasConfig(projects: string[]): void {
for (const dir of projects) {
const hasCfg = fs.existsSync(path.join(dir, 'package.json')) && require(path.join(dir,'package.json')).jest
|| EXTS.some(e => fs.existsSync(path.join(dir, `jest.config${e}`)));
if (!hasCfg) throw new Error(`Project ${dir} has no jest config; add one or remove from projects`);
}
} Prevention
- In a monorepo, give every package its own jest.config with a unique displayName.
- Run jest --showConfig to confirm each project resolves to a distinct config path.
- Avoid listing the root directory as both root and a projects entry.
When it happens
Trigger: projects: ['packages/a', 'packages/b'] where one directory lacks its own jest.config.*; two project paths that both resolve up to the root config; a glob in projects that yielded overlapping directories.
Common situations: Monorepo where a new package was added without a jest.config; projects pointing at empty/non-config directories; naming two project paths identically after normalization; mixing absolute and relative paths that resolve to the same location.
Related errors
- babel-jest: Babel ignores
- Cannot find module
- Cannot merge config in form of callback
- Could not resolve a module for a custom reporter. Module…
- haste.enableSymlinks is incompatible with watchman
AI-assisted analysis of jestjs/jest@8e6d128e4a (2026-08-10).
Data as JSON: /api/errors/774c053d13fa77c4.
Report an issue: GitHub.
Appendix: 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 8e6d128e4a)