How to fix Error: EMFILE: too many open files, watch in Node.js
This error occurs when fs.watch() exceeds the operating system limit for file watchers. File system watchers consume limited system resources, and watching too many files simultaneously exhausts these limits.
Quick fix
Fixes EMFILE
# Check the inotify watch limit
cat /proc/sys/fs/inotify/max_user_watches
# Typical output: 8192- Check your system inotify limit on Linux
- Temporarily increase inotify limit for testing
- Permanently increase inotify limit on Linux
- Exclude unnecessary directories from watching
# Check the inotify watch limitcat /proc/sys/fs/inotify/max_user_watches# Typical output: 8192Error: EMFILE: too many open files, watch
What this error means
The fs.watch() limit exceeded error is a system-level resource constraint that occurs when your Node.js application attempts to watch more files than the operating system permits. Unlike general file descriptor limits, file system watchers use a separate system resource pool that is often more limited. On Linux systems, inotify is used for file watching, with a default limit of 8192 watches per user. On macOS, FSEvents has different limitations, and on Windows, directory change notifications have their own constraints. When you exceed these limits, fs.watch() fails with an EMFILE error. This is particularly common in development tools, build systems, and file monitoring applications that watch entire project directories recursively. Each file or directory being watched consumes one watch handle from the system pool.
Typical symptoms
- fs.watch() fails with "Error: EMFILE: too many open files, watch"
- File watcher stops working after watching multiple directories
- Build tools or development servers fail to start when projects have many files
- Error occurs specifically when using fs.watch() or fs.watchFile() on large codebases
- Problem appears only on Linux systems, not on macOS or Windows
- IDE or editor file watcher crashes when opening large projects
Common causes
- Watching too many files or directories recursively without filtering
- System inotify limit on Linux is too low for the number of watched files
- Watching entire project directories including node_modules without exclusions
- Multiple watch instances competing for the same system resource limit
- Not properly closing watch instances when they are no longer needed
- Watching generated files or cache directories that contain thousands of files
How to fix "Error: EMFILE: too many open files, watch"
First, verify the current file watch limit on your system:
# Check the inotify watch limit
cat /proc/sys/fs/inotify/max_user_watches
# Typical output: 8192If the number is 8192 or lower and you're watching many files, this is likely your issue. The default limit is often insufficient for large projects.
To quickly test if increasing the limit fixes the problem:
# Increase to 65536
sudo sysctl -w fs.inotify.max_user_watches=65536
# Then run your Node.js application
node your-app.jsThis change applies immediately but will reset when you reboot. Use this to confirm the fix before making it permanent.
To make the change permanent across reboots, edit /etc/sysctl.conf:
sudo nano /etc/sysctl.confAdd this line at the end:
fs.inotify.max_user_watches=65536Save and apply the changes:
sudo sysctl -pVerify the new limit:
cat /proc/sys/fs/inotify/max_user_watchesThe most practical solution is to watch fewer files by excluding large directories:
const fs = require('fs');
const path = require('path');
function watchDir(dir, callback, excludeDirs = []) {
const files = fs.readdirSync(dir);
files.forEach(file => {
const filePath = path.join(dir, file);
const stat = fs.statSync(filePath);
// Skip excluded directories
if (stat.isDirectory() && excludeDirs.includes(file)) {
return;
}
if (stat.isDirectory()) {
watchDir(filePath, callback, excludeDirs);
} else {
fs.watch(filePath, callback);
}
});
}
// Watch src directory but exclude node_modules, dist, .git
watchDir('./src', (eventType, filename) => {
console.log('File changed:', filename);
}, ['node_modules', 'dist', '.git', '.next', 'build']);chokidar is more efficient than fs.watch and provides better control:
npm install chokidarconst chokidar = require('chokidar');
// Watch only necessary files
const watcher = chokidar.watch(['src/**/*.js', 'src/**/*.ts'], {
ignored: ['**/node_modules', '**/.git', '**/dist'],
usePolling: false,
awaitWriteFinish: {
stabilityThreshold: 100,
pollInterval: 100
}
});
watcher
.on('change', (path) => console.log('File changed:', path))
.on('add', (path) => console.log('File added:', path))
.on('unlink', (path) => console.log('File removed:', path))
.on('error', (error) => console.error('Watcher error:', error));
// Properly close watchers
process.on('SIGINT', () => {
watcher.close();
process.exit(0);
});Instead of watching directories recursively, watch only the files you care about:
const glob = require('glob');
const fs = require('fs');
// Find all source files matching pattern
glob('src/**/*.{js,ts,jsx,tsx}', (err, files) => {
if (err) throw err;
files.forEach(file => {
fs.watch(file, (eventType, filename) => {
console.log('Changed:', filename);
});
});
});This watches only source files and ignores build output, dependencies, and other unnecessary files.
Always close watch instances when done to free up resources:
const fs = require('fs');
const watcher = fs.watch('file.txt', (eventType, filename) => {
console.log('File changed:', filename);
});
// Later, close the watcher
watcher.close();
// Or for multiple watchers, close all
const watchers = [];
function closeAllWatchers() {
watchers.forEach(w => w.close());
watchers.length = 0;
}
process.on('SIGINT', () => {
closeAllWatchers();
process.exit(0);
});If your use case allows, use more efficient approaches than file watching:
// Instead of watching for changes, use polling with debouncing
const debounce = require('lodash.debounce');
const fs = require('fs').promises;
const checkFile = debounce(async () => {
const stats = await fs.stat('config.json');
console.log('Config modified:', stats.mtime);
}, 500);
fs.watch('config.json', () => checkFile());
// Or use fs.watchFile for single files
fs.watchFile('config.json', (current, previous) => {
if (current.mtime !== previous.mtime) {
console.log('Config changed');
}
});Advanced notes
Platform-Specific Limits: On Linux, the inotify limit (/proc/sys/fs/inotify/max_user_watches) is the primary constraint. On macOS, FSEvents is unlimited for the OS but Node.js may have practical limits. Windows directory change notifications are less resource-constrained but have different behavior.
Docker Environments: When running Node.js in Docker containers, the inotify limit is inherited from the host system. Increase it on the host or use --sysctl fs.inotify.max_user_watches=65536 when running Docker containers.
Production Considerations: In production, avoid using fs.watch() altogether. Instead, use message queues, webhooks, or external monitoring. File watching is primarily a development tool.
Chokidar vs fs.watch: Chokidar is more reliable and efficient than native fs.watch() for most use cases. It handles edge cases better and provides progress reporting. Consider it the standard for professional development tools.
Memory Efficiency: Each watch instance consumes memory in addition to system watch limits. Watching thousands of files not only hits system limits but also consumes significant RAM. Filtering is essential.
IDE Integration: Development environments (VS Code, WebStorm, etc.) may have their own file watcher limits that interact with your Node.js application's limits. Check IDE settings if watching doesn't work as expected.
Frequently asked questions
- What does "EMFILE" mean?
- js application attempts to watch more files than the operating system permits. Unlike general file descriptor limits, file system watchers use a separate system resource pool that is often more limited. On Linux systems, inotify is used for file watching, with a default limit of 8192 watches per user.
- How do I fix "EMFILE"?
- This error occurs when fs.watch() exceeds the operating system limit for file watchers. File system watchers consume limited system resources, and watching too many files simultaneously exhausts these limits.
- What causes "EMFILE"?
- Watching too many files or directories recursively without filtering System inotify limit on Linux is too low for the number of watched files Watching entire project directories including node_modules without exclusions
- Is the "EMFILE" error serious?
- Yes. This is a high-severity error that usually blocks work until it is fixed, but the steps above resolve it.
Official resources & further reading
- ๐Node.js Official Documentation
- ๐
- ๐github.com - chokidar(GitHub)
- ๐
- ๐ฌstackoverflow.com - grunt watch error emfile too many open files(Stack Overflow)