{"record":{"id":"58a6603753db9418","repo":"jestjs/jest","slug":"duplicated-files-or-mocks-please-check-the-consol","errorCode":null,"errorMessage":"Duplicated files or mocks. Please check the console for more info","messagePattern":"Duplicated files or mocks\\. Please check the console for more info","errorType":"exception","errorClass":"DuplicateError","httpStatus":null,"severity":"error","filePath":"packages/jest-haste-map/src/lib/FileProcessor.ts","lineNumber":106,"sourceCode":"        H.GENERIC_PLATFORM;\n\n      const existingModule = moduleMap[platform];\n\n      if (existingModule && existingModule[H.PATH] !== module[H.PATH]) {\n        const method = this._options.throwOnModuleCollision ? 'error' : 'warn';\n\n        this._console[method](\n          [\n            `jest-haste-map: Haste module naming collision: ${id}`,\n            '  The following files share their name; please adjust your hasteImpl:',\n            `    * <rootDir>${path.sep}${existingModule[H.PATH]}`,\n            `    * <rootDir>${path.sep}${module[H.PATH]}`,\n            '',\n          ].join('\\n'),\n        );\n\n        if (this._options.throwOnModuleCollision) {\n          throw new DuplicateError(existingModule[H.PATH], module[H.PATH]);\n        }\n\n        // We do NOT want consumers to use a module that is ambiguous.\n        delete moduleMap[platform];\n\n        if (Object.keys(moduleMap).length === 0) {\n          map.delete(id);\n        }\n\n        let dupsByPlatform = hasteMap.duplicates.get(id);\n        if (dupsByPlatform == null) {\n          dupsByPlatform = new Map();\n          hasteMap.duplicates.set(id, dupsByPlatform);\n        }\n\n        const dups = new Map([\n          [module[H.PATH], module[H.TYPE]],\n          [existingModule[H.PATH], existingModule[H.TYPE]],","sourceCodeStart":88,"sourceCodeEnd":124,"githubUrl":"https://github.com/jestjs/jest/blob/8e6d128e4a278059ecddecaa97400b04c8ae5fd9/packages/jest-haste-map/src/lib/FileProcessor.ts#L88-L124","documentation":"Two different files resolve to the SAME haste module ID for the SAME platform (e.g. two `Foo.js` without platform extensions, or `Foo.js` and `Foo.ts` both yielding ID 'Foo'). When `throwOnModuleCollision` is enabled, FileProcessor.processFile's setModule() aborts the build by throwing a DuplicateError carrying both file paths. Without that flag it only warns and removes the ambiguous entry.","triggerScenarios":"In processFile, setModule() finds an existingModule for the same platform whose path differs from the new module (index.ts FileProcessor.ts:92). With `throwOnModuleCollision: true`, a DuplicateError is thrown at line 106. The console also prints both colliding paths before the throw.","commonSituations":"Adding a `.ts` duplicate of an existing `.js` file without platform disambiguation; two packages exporting the same haste name; stale build artifacts (`.js.map` vs `.js`) left in roots; switching a project to TypeScript while old compiled JS remains in the crawl path.","solutions":["Look at the console output immediately before the throw — it names both colliding files; delete or rename one.","Add a platform extension (e.g. `Foo.ios.js`) if the files are intentionally platform-specific.","Remove stale compiled output or build artifacts from the roots (`npm run clean`, clear `dist/`).","If collisions are expected and non-fatal, set `throwOnModuleCollision: false` (the default) — collisions become warnings.","Configure a custom `hasteImplModulePath` to derive unique IDs if the default name extraction is too coarse."],"exampleFix":"// before: both src/Foo.js and src/Foo.ts exist, both yield haste ID 'Foo'\n// after: remove the compiled JS or namespace it\n//   rm src/Foo.js   (keep Foo.ts)\n// or rename: src/Foo.legacy.js","handlingStrategy":"validation","validationCode":"// Pre-scan for haste ID collisions before running Jest.\nimport glob from 'fast-glob';\nimport path from 'node:path';\nasync function findHasteCollisions(roots: string[], extensions: string[]) {\n  const byId = new Map<string, string[]>();\n  const pattern = roots.map(r => `${r}/**/*.{${extensions.join(',')}}`);\n  for (const file of await glob(pattern)) {\n    const id = path.basename(file).replace(/\\.[^.]+$/, '');\n    if (!byId.has(id)) byId.set(id, []);\n    byId.get(id)!.push(file);\n  }\n  const collisions = [...byId.entries()].filter(([, files]) => files.length > 1);\n  if (collisions.length) console.warn('Haste collisions:', collisions);\n  return collisions;\n}","typeGuard":null,"tryCatchPattern":"try {\n  await hasteMap.build();\n} catch (error) {\n  if (error.constructor.name === 'DuplicateError') {\n    console.error(`Collision: ${error.mockPath1} vs ${error.mockPath2}`);\n    // decide: delete one, or disable throwOnModuleCollision\n  }\n  throw error;\n}","preventionTips":["Run `jest --listTests` or a collision pre-scan in CI to catch duplicates early.","Clean build output (dist/build) before running tests to avoid .js/.ts collisions.","Use platform extensions or distinct filenames for intentional multi-platform modules.","Set `throwOnModuleCollision: false` in watch mode (the library does this automatically)."],"tags":["duplicate","haste","module-collision","typescript","build-artifacts"],"backgroundTag":null,"analyzedSha":"8e6d128e4a278059ecddecaa97400b04c8ae5fd9","analyzedAt":"2026-08-10T18:11:27.960Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}