Back to results for “File System”
Node.js › File System (fs) Module

What are Node.js file descriptor limits, and how might a Node.js application unintentionally exhaust them?

Advanced

Answer

Every open file, network socket, or pipe consumes a file descriptor, and the operating system imposes a limit on how many a single process can have open simultaneously (often 1024 by default on many systems) -- an application that opens files or streams without properly closing them (a common bug when error paths forget to close a stream, or when a loop opens many file handles concurrently without bounding concurrency) can exhaust this limit, causing subsequent file or network operations to fail with an EMFILE error.
// Leak: file handle never closed if an error occurs mid-processing
const fd = await fs.open('data.txt', 'r');
await processFile(fd); // if this throws, fd.close() below is never reached
await fd.close();

// Fixed: guarantees the descriptor is always released
const fd = await fs.open('data.txt', 'r');
try {
  await processFile(fd);
} finally {
  await fd.close();
}
Real-world example A batch job processing thousands of files started failing partway through with 'EMFILE: too many open files' errors, traced to a bug where an error thrown during processing skipped the file-close call for that iteration; wrapping the close call in a finally block ensured file descriptors were always released regardless of whether processing succeeded or failed.

Common follow-ups: How would you check and adjust the OS-level file descriptor limit (ulimit) for a Node.js process that legitimately needs to handle many concurrent connections?;How does concurrency-limiting a batch operation (as discussed for async task queues) also help prevent this kind of file descriptor exhaustion?