Skip to content
Latchkey

Node.js "EMFILE: too many open files" - Fix the File-Descriptor Limit

Node hit the operating system’s open-file-descriptor limit. A build, watcher, or test run that opens thousands of files at once exhausts the nofile limit and the next open() fails with EMFILE.

What this error means

A build, lint, or test run aborts with EMFILE: too many open files, often pointing at a file read or a watcher. It can be intermittent depending on how many handles are open at the peak, and is environment-specific to the runner’s ulimit.

Node output
Error: EMFILE: too many open files, open '/app/node_modules/.../index.js'
    at Object.openSync (node:fs:603:3)
  errno: -24,
  code: 'EMFILE',
  syscall: 'open'

Common causes

The descriptor limit is too low for the workload

Containers and CI runners often ship a modest ulimit -n (e.g. 1024). A large monorepo build or a recursive watcher opens more handles than that at peak.

Too many files opened concurrently

Code that fans out unbounded fs reads (e.g. Promise.all over thousands of files) holds many descriptors open simultaneously, crossing the limit even when it is reasonable.

How to fix it

Raise the open-file limit

Increase nofile for the job. On most runners you can raise the soft limit toward the hard limit in the step.

Terminal
ulimit -n 65535
node build.mjs

Bound the concurrency of file operations

  1. Replace unbounded Promise.all over files with a concurrency-limited queue.
  2. Increase the watcher’s polling/ignore config so it does not watch node_modules.
  3. Use graceful-fs if a dependency floods descriptors and you cannot raise the limit.

How to prevent it

  • Set a generous ulimit -n in CI for build/test steps.
  • Cap concurrent file reads with a queue rather than fanning out unbounded.
  • Exclude node_modules from file watchers.

Related guides

Tired of flaky CI? Latchkey auto-heals failed jobs and retries them for you. Start free →