The EMFILE error occurs when npm exceeds the operating system's file descriptor limit, typically during large installs or builds. The fix involves increasing the ulimit or using graceful-fs to handle file operations more efficiently.
The EMFILE error (Enumeration of too Many FILES) is a system-level error that occurs when a Node.js process attempts to open more file descriptors than the operating system allows. File descriptors are references to open resources—not just files on disk, but also network sockets, pipes, and streams. Each open file, network connection, or I/O resource consumes one file descriptor from your system's limit. When you hit that limit and try to open another resource, the operating system rejects the operation with an EMFILE error, causing npm to crash. In npm specifically, this happens during npm install, npm run build, or npm run dev when the build tool or package manager tries to open too many files simultaneously. On Linux systems, the default limit is typically 1024 file descriptors per process—a number that modern bundlers like Webpack, Vite, and Rollup regularly exceed, especially when working with large projects containing thousands of source files.
Run this command to see your system's current limit:
ulimit -nTypical output on Linux is 1024. On macOS with recent versions, you might see higher values like 7168. Anything below 4096 is likely too low for modern npm workflows.
You can also check the system-wide limit (Ubuntu/Debian):
sysctl -a | grep fs.file-maxThis is the quickest fix to test if raising the limit solves your problem:
# Increase to 65536 (sufficient for most projects)
ulimit -n 65536
# Verify the change
ulimit -nThen run your npm command again:
npm run dev
# or
npm installIf this fixes the error, the problem is confirmed. Note: This change only affects the current terminal session.
To make the change permanent across reboots, edit the system limits file:
sudo nano /etc/security/limits.confAdd these two lines at the end (replace yourusername with your actual username):
yourusername soft nofile 65536
yourusername hard nofile 65536For all users on the system, use:
* soft nofile 65536
* hard nofile 65536Save the file. Then log out and log back in for the changes to take effect. Verify with ulimit -n.
macOS users can improve file watching efficiency by installing Watchman:
# Using Homebrew
brew install watchman
# Verify installation
watchman versionWatchman reduces the number of file descriptors needed for watching large projects during development. This is particularly helpful for React and Next.js projects.
If you can't modify system limits (e.g., in CI/CD environments), switch your dev server to polling mode:
# For Webpack-based projects (Create React App, etc.)
WATCHPACK_POLLING=true npm run dev
# For Vite projects
npm run dev -- --watch-use-pollingTo make this permanent in your .bashrc or .zshrc:
echo 'export WATCHPACK_POLLING=true' >> ~/.bashrc
source ~/.bashrcTrade-off: Polling mode is slightly less responsive but uses fewer resources.
The graceful-fs npm package provides automatic backoff and queuing when EMFILE errors occur:
npm install --save graceful-fsThen, in your application's entry point (before other requires):
// At the very top of your main file
const gracefulFs = require('graceful-fs');
const fs = require('fs');
// Patch the fs module globally
gracefulFs.gracefulify(fs);
// Now continue with the rest of your codeThis converts EMFILE crashes into slower but functional operations by queuing file operations.
File Descriptor Internals: Unix-like systems treat "everything as a file," including actual files, directories, network sockets, pipes, and devices. Each gets a file descriptor (a small integer). The kernel enforces per-process limits (ulimit) to prevent one runaway process from exhausting system resources.
You can inspect open file descriptors for a running process using: lsof -p <PID>
Windows Limitations: Windows has a different file descriptor model. The EMFILE error is less common on Windows because the system allows higher counts by default. However, if running npm via WSL2, it inherits Linux's limits.
Graceful Degradation: graceful-fs doesn't prevent EMFILE; it converts the error into a queue. When a file operation fails with EMFILE, graceful-fs waits 1ms, closes one file descriptor, and retries. This trades latency for reliability.
Monorepos and Workspaces: Monorepos are particularly prone to EMFILE because they create multiple levels of node_modules. Yarn 3+ or pnpm use symlinks and flatter structures, reducing EMFILE risk.
Detecting Leaks: If increasing ulimit doesn't resolve the issue, suspect a file descriptor leak. Use lsof -p <PID> | wc -l to see file descriptor count over time. Steady increases indicate a leak.
npm ERR! code E401 npm ERR! 401 Unauthorized - Token has expired
Token has expired - npm authentication failure
npm ERR! code EAI_NODATA npm ERR! errno EAI_NODATA npm ERR! getaddrinfo EAI_NODATA registry.npmjs.org
How to fix "npm ERR! code EAI_NODATA - getaddrinfo EAI_NODATA"
npm ERR! code EMPTYPACKAGE npm ERR! Package contains no files
How to fix 'npm ERR! code EMPTYPACKAGE' - Package contains no files
npm ERR! code EWORKSPACEMISSING npm ERR! Workspace does not exist: packages/missing
How to fix "npm ERR! code EWORKSPACEMISSING - Workspace does not exist" error
npm ERR! code EADDRNOTAVAIL npm ERR! errno EADDRNOTAVAIL npm ERR! Address not available
How to fix "npm ERR! code EADDRNOTAVAIL - Address not available" error