Skip to content

ng serve crashes with EMFILE: too many open files, watch on macOS when preserveSymlinks is enabled (22.2 regression) #34312

Closed

Description

@myabc

Command

serve

Is this a regression?

  • Yes, this behavior used to work in the previous version

The previous version in which this bug was not present was

22.1.9

Description

Since 22.2.0, ng serve (and any watch build) crashes on macOS right after the first successful build when the build target sets preserveSymlinks: true and the workspace contains more than 4096 directories outside node_modules.

setupWatcher passes preserveSymlinks on as followSymlinks, and createWatcher then always picks chokidar over @parcel/watcher:

if (options?.polling || options?.followSymlinks) {
  return createChokidarWatcher(options);
}

Chokidar 5 calls fs.watch once per directory and file under the workspace root. On macOS, Node reports EMFILE as soon as one process holds more than 4096 directory watches: 4096 fs.watch calls on directories work, 4097 fail. File watches do not count towards this (50,000 worked), and ulimit -n has no influence: the crash reproduces with the hard limit at unlimited.

The error is emitted on the FSWatcher without a listener, so the dev server process exits.

In our application (about 1,250 source directories plus the packages it imports from node_modules, which chokidar also watches whole) the dev server made 33,703 fs.watch calls before crashing. With 22.1.9 and watchpack the same workspace needs 4. We depend on preserveSymlinks because plugin frontends are symlinked into src/.

Minimal Reproduction

On macOS:

npx @angular/cli@22.2 new emfile-repro --defaults --skip-git
cd emfile-repro
node -e "for (let i = 0; i < 4200; i++) fs.mkdirSync('many/d' + i, { recursive: true })"
npx ng config projects.emfile-repro.architect.build.options.preserveSymlinks true
npx ng serve

The server prints its local URL and exits a moment later with the error below. It keeps running with preserveSymlinks unset, or with 3000 directories instead of 4200.

Exception or Error

Error: EMFILE: too many open files, watch
    at FSWatcher._handle.onchange (node:internal/fs/watchers:267:21)
Emitted 'error' event on FSWatcher instance at:
    at FSWatcher._handleError (node_modules/chokidar/index.js:558:18)
    at NodeFsHandler._boundHandleError (node_modules/chokidar/handler.js:297:49)
    at node_modules/chokidar/handler.js:144:9
    at foreach (node_modules/chokidar/handler.js:76:9)
    at fsWatchBroadcast (node_modules/chokidar/handler.js:143:5)
    at FSWatcher.<anonymous> (node_modules/chokidar/handler.js:191:17)
    at FSWatcher.emit (node:events:509:28)
    at FSWatcher._handle.onchange (node:internal/fs/watchers:273:12) {
  errno: -24,
  syscall: 'watch',
  code: 'EMFILE',
  filename: null
}

Your Environment

Angular CLI       : 22.2.2
Angular           : 22.2.2
Node.js           : 24.18.0
Package Manager   : npm 11.16.0
Operating System  : darwin arm64 (macOS 27.0.1)

@angular/build            22.2.2
@angular/cli              22.2.2
@angular/compiler-cli     22.2.2
typescript                6.0.3

Anything else relevant?

@parcel/watcher loads and subscribes fine on the same machine, so this is not the load-failure fallback. With preserveSymlinks off the dev server holds no fs.watch handles at all. Would it be possible to keep the parcel watcher for preserveSymlinks workspaces, or to limit chokidar to the files the build actually reports instead of the whole workspace root?

Workaround: pin @angular/build to 22.1.9, or run with --watch false.

Activity

  1. added this to the needsTriage milestone on Oct 12, 2026
  2. added 5 commits that reference this issue on Oct 15, 2026
    fdc64f7
    457a776
    d170c55
    6aff4ed
    60b40f3
  3. added a commit that references this issue on Oct 16, 2026
  4. added a commit that references this issue on Oct 16, 2026
    a057239
  5. added a commit that references this issue on Oct 16, 2026
    972302a
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions