jestjs/jest · error · ValidationError
haste.enableSymlinks is incompatible with watchman
Error message
haste.enableSymlinks is incompatible with watchman
What it means
Near the end of normalize (packages/jest-config/src/normalize.ts:1060), Jest validates that `haste.enableSymlinks` is not combined with `watchman: true`. Watchman's file crawling does not follow symlinks the way Jest's haste-map symlink support expects, so enabling both produces incorrect module resolution; Jest throws a ValidationError.
Source
Thrown at packages/jest-config/src/normalize.ts:1061
return {
config: watchPlugin[1] || {},
path: resolveWatchPlugin(newOptions.resolver, {
filePath: watchPlugin[0],
requireResolveFunction: requireResolve,
rootDir: options.rootDir,
}),
};
}
});
break;
}
// @ts-expect-error: automock is missing in GlobalConfig, so what
newOptions[key] = value;
return newOptions;
}, newOptions);
if (options.watchman && options.haste?.enableSymlinks) {
throw new ValidationError(
'Validation Error',
'haste.enableSymlinks is incompatible with watchman',
'Either set haste.enableSymlinks to false or do not use watchman',
);
}
for (const [i, root] of newOptions.roots.entries()) {
verifyDirectoryExists(root, `roots[${i}]`);
}
try {
// try to resolve windows short paths, ignoring errors (permission errors, mostly)
newOptions.cwd = tryRealpath(process.cwd());
} catch {
// ignored
}
newOptions.testSequencer = resolveSequencer(newOptions.resolver, {View on GitHub (pinned to f49721c78e)
Solutions
- Disable watchman: set `watchman: false` (Jest will fall back to its own crawler which supports symlinks).
- Or disable symlink support: set `haste: { enableSymlinks: false }` if you do not actually need symlink following.
Example fix
// before
module.exports = {
watchman: true, // default
haste: { enableSymlinks: true },
};
// after (option A: keep symlinks, drop watchman)
module.exports = {
watchman: false,
haste: { enableSymlinks: true },
}; Defensive patterns
Strategy: validation
Validate before calling
function validateHasteWatchman(cfg: { watchman?: boolean; haste?: { enableSymlinks?: boolean } }): void {
if (cfg.watchman !== false && cfg.haste?.enableSymlinks) {
throw new Error('haste.enableSymlinks requires watchman:false');
}
} Type guard
const symlinksEnabled = (cfg: any) => Boolean(cfg?.haste?.enableSymlinks); const watchmanEnabled = (cfg: any) => cfg?.watchman !== false;
Prevention
- If you need symlink support, set `watchman: false`.
- Default watchman is on; explicitly disable it when enabling haste.enableSymlinks.
- Document the trade-off: Jest's crawler is slower than watchman.
When it happens
Trigger: Configuring `{ watchman: true, haste: { enableSymlinks: true } }` (watchman is on by default, so merely adding `haste.enableSymlinks: true` is enough to trigger it unless watchman is explicitly disabled).
Common situations: Enabling symlink support for a monorepo that uses symlinks/yarn workspaces/pnpm, while leaving the default watchman crawler enabled.
Related errors
- jest-haste-map: enableSymlinks config option was set, but is
- seed value must be `-0x80000000` and `0x7fffffff` inclusive
- @jest/diff-sequences: ${name} typeof ${typeof arg} is not a
- @jest/diff-sequences: ${name} value ${arg} is not a safe int
- @jest/diff-sequences: ${name} value ${arg} is a negative int
AI-assisted analysis of jestjs/jest@f49721c78e (2026-08-03).
Data as JSON: /data/errors/85c7eec12f791c4d.json.
Report an issue: GitHub.