jestjs/jest · error · DuplicateHasteCandidatesError

The name ` ` was looked up in the Haste module map. It…

Error message

The name `${name}` was looked up in the Haste module map. It cannot be resolved, because there exists several different files, or packages, that provide a module for that particular name and platform. ${platformMessage} You must delete or exclude files until there remains only one of these:

${duplicatesList}

What it means

Thrown as `DuplicateHasteCandidatesError` when module resolution finds multiple files or packages providing the same haste module name for the same platform. Jest's haste map requires names to be unique per platform; when duplicates exist, it cannot decide which file to resolve and lists all candidates.

Solutions

  1. Read the error — it lists all conflicting file paths and their types (module/package).
  2. Delete, rename, or exclude one of the duplicate files so only one remains for that name+platform.
  3. Add the conflicting path to `modulePathIgnorePatterns` or ` haste.retainAllFiles: false` scope.
  4. If duplicates come from node_modules symlinks in a monorepo, configure `haste.enableSymlinks` or dedupe with the package manager.
  5. Rename the `@providesModule` declaration in one of the files.

Example fix

// before: two files both declare
// src/Foo.js
/** @providesModule Foo */
// src/components/Foo.js  (accidental copy)
/** @providesModule Foo */

// after: remove the duplicate or rename it
// src/components/Foo.js
/** @providesModule NewFoo */
Defensive patterns

Strategy: validation

Validate before calling

// Scan for duplicate @providesModule declarations before running Jest
const fs = require('fs');
const path = require('path');
function findDuplicateHasteNames(rootDir) {
  const names = new Map();
  function walk(dir) {
    for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
      if (entry.name === 'node_modules') continue;
      const full = path.join(dir, entry.name);
      if (entry.isDirectory()) { walk(full); }
      else if (/\.js$/.test(entry.name)) {
        const content = fs.readFileSync(full, 'utf8');
        const match = content.match(/@providesModule\s+(\S+)/);
        if (match) {
          if (names.has(match[1])) {
            throw new Error(`Duplicate @providesModule ${match[1]}: ${names.get(match[1])} and ${full}`);
          }
          names.set(match[1], full);
        }
      }
    }
  }
  walk(rootDir);
}

Try / catch

try {
  const modulePath = hasteMap.getModule(name, platform);
  if (!modulePath) throw new Error(`Cannot resolve module: ${name}`);
} catch (e) {
  if (e.constructor.name === 'DuplicateHasteCandidatesError') {
    console.error('Haste name collision:', e.hasteName, e.duplicatesSet);
    // Guide user to deduplicate
  }
  throw e;
}

Prevention

When it happens

Trigger: Two files declaring the same `@providesModule` name, two `package.json` files with the same `name` in different directories both reachable by the haste map, or platform-specific files (e.g. `Foo.js` and `Foo.ios.js`) that resolve to the same generic platform. The error is thrown from `_assertNoDuplicates` during `getModule`/`getPackage`.

Common situations: React Native projects where `@providesModule` annotations collide. Monorepo with multiple packages sharing the same npm name. Accidental file duplication (copy-paste). A symlink creating a second path to the same haste-decorated file. Migrating to haste and having leftover declarations.

Related errors


AI-assisted analysis of jestjs/jest@8e6d128e4a (2026-08-10). Data as JSON: /api/errors/d80cd4f9c73b950d. Report an issue: GitHub.

Appendix: source

Thrown at packages/jest-haste-map/src/ModuleMap.ts:191

  private _assertNoDuplicates(
    name: string,
    platform: string,
    supportsNativePlatform: boolean,
    relativePathSet: DuplicatesSet | null,
  ) {
    if (relativePathSet == null) {
      return;
    }
    // Force flow refinement
    const previousSet = relativePathSet;
    const duplicates = new Map();

    for (const [relativePath, type] of previousSet) {
      const duplicatePath = fastPath.resolve(this._raw.rootDir, relativePath);
      duplicates.set(duplicatePath, type);
    }

    throw new DuplicateHasteCandidatesError(
      name,
      platform,
      supportsNativePlatform,
      duplicates,
    );
  }

  static create(rootDir: string): ModuleMap {
    return new ModuleMap({
      duplicates: new Map(),
      map: new Map(),
      mocks: new Map(),
      rootDir,
    });
  }
}

class DuplicateHasteCandidatesError extends Error {

View on GitHub (pinned to 8e6d128e4a)