jestjs/jest · error · AggregateError
Failed to start watch mode.
Error message
Failed to start watch mode.
What it means
When jest-haste-map starts watch mode, it instantiates one watcher per root and waits for each to emit 'ready' within 240 seconds. If any watcher rejects (emits 'error' during startup) or times out without becoming ready, WatcherDriver.start throws an AggregateError whose message is 'Failed to start watch mode.' The AggregateError's `errors` array contains the per-root rejection reasons.
Solutions
- Check the AggregateError's `errors` array for the per-root cause — `catch(e) { console.error(e.errors) }`.
- Raise the Linux inotify limit: `echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p`.
- Remove or fix any non-existent root directory from the Jest config.
- Reinstall native deps (`npm rebuild`) if @parcel/watcher binding is missing.
- If using watchman, run `watchman version` and `watchman shutdown-server`, then restart.
Example fix
// before — root doesn't exist
module.exports = { roots: ['<rootDir>/src', '<rootDir>/deleted-pkg'] };
// after
module.exports = { roots: ['<rootDir>/src'] }; Defensive patterns
Strategy: validation
Validate before calling
// Verify roots and inotify limits before starting watch mode (Linux).
import { existsSync } from 'node:fs';
import { readFileSync } from 'node:fs';
function checkWatchPrereqs(roots: string[]) {
const missing = roots.filter(r => !existsSync(r));
if (missing.length) throw new Error(`Unwatchable roots: ${missing.join(', ')}`);
if (process.platform === 'linux') {
const max = readFileSync('/proc/sys/fs/inotify/max_user_watches', 'utf8').trim();
if (Number(max) < 524288) {
console.warn(`inotify max_user_watches=${max} is low; consider raising it.`);
}
}
} Try / catch
try {
await watcherDriver.start(onChange);
} catch (error) {
if (error instanceof AggregateError) {
for (const reason of error.errors) console.error('Root watcher failed:', reason);
}
throw error;
} Prevention
- Validate every root exists before enabling watch mode.
- On Linux, raise `fs.inotify.max_user_watches` to 524288+.
- Ensure @parcel/watcher native bindings are installed (`npm rebuild`).
- Restart stale watchman daemons with `watchman shutdown-server`.
When it happens
Trigger: WatcherDriver.start uses Promise.allSettled over _createWatcher calls (line 71). A watcher's 'error' event fires during startup (onStartupError rejects), or the 240s MAX_WAIT_TIME timeout fires (line 121-126) rejecting with this same message. When any root is rejected, all fulfilled watchers are closed and the AggregateError is thrown at line 82.
Common situations: A root directory does not exist or is not watchable; watchman subscription fails; @parcel/watcher native binding crashes or is missing on the platform; inotify watch limit exhausted on Linux (`fs.inotify.max_user_watches` too low); very large repos where 240s is insufficient for the initial crawl.
Related errors
- Crawler retry failed: Original error
- jest-haste-map: enableSymlinks config option was set, but…
- Watch plugin configuration error
- Attempted to display seed but seed value is undefined
- babel-jest: Babel ignores
AI-assisted analysis of jestjs/jest@8e6d128e4a (2026-08-10).
Data as JSON: /api/errors/fca864b6669f07a4.
Report an issue: GitHub.
Appendix: source
Thrown at packages/jest-haste-map/src/watchers/index.ts:82
}
async start(onChange: OnChangeCallback): Promise<void> {
const Backend: WatcherCtor = this._useWatchman
? WatchmanWatcher
: ParcelWatcher;
const results = await Promise.allSettled(
this._roots.map(root => this._createWatcher(Backend, root, onChange)),
);
const fulfilled = results
.filter(r => r.status === 'fulfilled')
.map(r => (r as PromiseFulfilledResult<IWatcher>).value);
const rejected = results
.filter(r => r.status === 'rejected')
.map(r => (r as PromiseRejectedResult).reason);
if (rejected.length > 0) {
await Promise.allSettled(fulfilled.map(w => w.close()));
throw new AggregateError(rejected, 'Failed to start watch mode.');
}
this._watchers = fulfilled;
}
async close(): Promise<void> {
await Promise.all(this._watchers.map(watcher => watcher.close()));
this._watchers = [];
}
private _createWatcher(
Backend: WatcherCtor,
root: string,
onChange: OnChangeCallback,
): Promise<IWatcher> {
const watcher = new Backend(root, {
console: this._console,
dot: true,
glob: this._extensions.map(ext => `**/*.${ext}`),View on GitHub (pinned to 8e6d128e4a)