{"id":"fba3e0ae6f23fe4d","repo":"jestjs/jest","slug":"whoops-two-projects-resolved-to-the-same-config-p","errorCode":null,"errorMessage":"Whoops! Two projects resolved to the same config path: ${String(configPath)}:\n\n  Project 1: ${projects[parsedConfigs.indexOf(config)]}\n  Project 2: ${projects[parsedConfigs.indexOf(configPathMap.get(configPath))]}\n\nThis usually means that your \"projects\" config includes a directory that doesn't have any configuration recognizable by Jest. Please fix it.","messagePattern":"Whoops! Two projects resolved to the same config path: (.+?):\n\n  Project 1: (.+?)\n  Project 2: (.+?)\n\nThis usually means that your \"projects\" config includes a directory that doesn't have any configuration recognizable by Jest\\. Please fix it\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/jest-config/src/index.ts","lineNumber":296,"sourceCode":"  for (const config of parsedConfigs) {\n    const {configPath} = config;\n\n    if (configPathMap.has(configPath)) {\n      const message = `Whoops! Two projects resolved to the same config path: ${chalk.bold(\n        String(configPath),\n      )}:\n\n  Project 1: ${chalk.bold(projects[parsedConfigs.indexOf(config)])}\n  Project 2: ${chalk.bold(\n    projects[parsedConfigs.indexOf(configPathMap.get(configPath))],\n  )}\n\nThis usually means that your ${chalk.bold(\n        '\"projects\"',\n      )} config includes a directory that doesn't have any configuration recognizable by Jest. Please fix it.\n`;\n\n      throw new Error(message);\n    }\n    if (configPath !== null) {\n      configPathMap.set(configPath, config);\n    }\n  }\n};\n\nexport interface ReadJestConfigOptions {\n  /**\n   * The package root or deserialized config (default is cwd)\n   */\n  packageRootOrConfig?: string | Config.InitialOptions;\n  /**\n   * When the `packageRootOrConfig` contains config, this parameter should\n   * contain the dirname of the parent config\n   */\n  parentConfigDirname?: null | string;\n  /**","sourceCodeStart":278,"sourceCodeEnd":314,"githubUrl":"https://github.com/jestjs/jest/blob/f49721c78e195558b40913977c9230f5b7f559d8/packages/jest-config/src/index.ts#L278-L314","documentation":"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.","triggerScenarios":"`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.","commonSituations":"Monorepos where some packages lack per-package config; renaming/removing a package's jest.config.js; glob expansion producing duplicate or nested paths.","solutions":["Give each project its own jest.config.{js,ts,...} so the resolved config paths differ.","If the projects genuinely share one config, list that config once instead of listing multiple bare directories.","Remove duplicate/overlapping entries from the `projects` array (check globs and symlinks)."],"exampleFix":"// before (root jest.config.js)\nmodule.exports = { projects: ['packages/a', 'packages/b'] }; // a & b have no config\n\n// after: give each package its own jest.config.js, or collapse to a single root config\nmodule.exports = { testEnvironment: 'node' };","handlingStrategy":"validation","validationCode":"import * as path from 'node:path';\nimport * as fs from 'node:fs';\nimport {constants} from 'jest-config';\nfunction assertDistinctProjectConfigs(roots: string[]): void {\n  const seen = new Set<string>();\n  for (const root of roots) {\n    const resolved = resolveProjectConfigPath(root);\n    if (seen.has(resolved)) throw new Error(`Duplicate resolved config path: ${resolved} (from ${root})`);\n    seen.add(resolved);\n  }\n}\n// resolveProjectConfigPath: find jest.config.* in root or walk up","typeGuard":"const isUniqueConfigPaths = (paths: string[]) => new Set(paths).size === paths.length;","tryCatchPattern":null,"preventionTips":["Give each monorepo package its own jest.config.* file.","Avoid listing bare directories that lack a config (they collapse to the parent).","Audit the projects array after moving/renaming packages."],"tags":["jest-config","projects","config","monorepo"],"analyzedSha":"f49721c78e195558b40913977c9230f5b7f559d8","analyzedAt":"2026-08-03T20:16:28.571Z","schemaVersion":2}