Fix: ENOSPC: System Limit for Number of File Watchers Reached
The Error
You’re running a dev server, test watcher, or VS Code, and you get one of these errors:
Node.js / React / Angular / webpack:
Error: ENOSPC: system limit for number of file watchers reached, watch '/home/you/project/src'Alternate wording:
ENOSPC: no space left on device, watchVS Code notification:
Visual Studio Code is unable to watch for file changes in this large workspacemacOS (related):
Error: EMFILE, too many open filesThese all point to the same root problem: your OS ran out of file watcher slots.
Why This Happens
Development tools watch your files for changes so they can auto-reload, recompile, or update your editor. Each watched file consumes one “watcher” from a limited OS pool.
On Linux, the kernel uses inotify for file watching. The default limit is often 8,192 watchers. That sounds like a lot, but a single node_modules folder can contain tens of thousands of files. Add a framework dev server, a test runner, VS Code, and maybe a bundler — you’ll hit the limit fast.
On macOS, the equivalent limit is the maximum number of open file descriptors (ulimit -n), which defaults to 256 in some configurations. The EMFILE error means you’ve hit that limit.
Common scenarios that trigger this:
- Large
node_modulestrees. A mid-sized React or Angular project can easily have 30,000+ files innode_modules. If you’re also hitting npm permission errors or dependency conflicts, fixing those first can reduce bloat. - Multiple tools watching simultaneously. VS Code, webpack-dev-server, Jest in watch mode, and nodemon can each create thousands of watchers.
- Monorepos. Multiple packages, each with their own
node_modules, multiply the problem. - WSL2. The default inotify limit inside WSL2 is the same low default as a standard Linux install.
Fix 1: Increase the Inotify Watcher Limit (Temporary)
Check your current limit:
cat /proc/sys/fs/inotify/max_user_watchesThe default is usually 8192. Increase it immediately:
sudo sysctl fs.inotify.max_user_watches=524288This takes effect instantly. No restart required. The error should stop.
However, this change is lost on reboot. See Fix 2 to make it permanent.
How to choose a value: 524288 (512K) is the value recommended by the VS Code documentation and used by most Linux distributions that ship a higher default. It uses roughly 256-280 MB of RAM on a 64-bit system (each watch consumes about 540 bytes in kernel memory). For most development machines with 8+ GB of RAM, this is negligible.
Fix 2: Make the Change Permanent
Method A: /etc/sysctl.conf
Add the setting to the system-wide sysctl config:
echo "fs.inotify.max_user_watches=524288" | sudo tee -a /etc/sysctl.confApply it without rebooting:
sudo sysctl -pMethod B: /etc/sysctl.d/ drop-in file (recommended)
Many modern distros prefer drop-in files over editing sysctl.conf directly:
echo "fs.inotify.max_user_watches=524288" | sudo tee /etc/sysctl.d/50-file-watchers.confApply it:
sudo sysctl --systemThis is cleaner because it keeps your custom settings separate from the distribution defaults, making upgrades easier.
Verify the change
cat /proc/sys/fs/inotify/max_user_watchesYou should see 524288.
Note: You may also want to increase max_user_instances if you run many watcher-heavy processes simultaneously:
echo "fs.inotify.max_user_instances=1024" | sudo tee -a /etc/sysctl.d/50-file-watchers.conf
sudo sysctl --systemThe default max_user_instances is 128, which limits how many separate inotify instances a single user can create.
Fix 3: Reduce the Number of Watched Files
Increasing the limit is the quick fix, but the better long-term approach is to stop watching files you don’t need to watch.
Exclude node_modules in your tool config
webpack (webpack.config.js):
module.exports = {
watchOptions: {
ignored: /node_modules/,
},
};Jest (jest.config.js):
module.exports = {
watchPathIgnorePatterns: ['<rootDir>/node_modules/'],
};nodemon (nodemon.json):
{
"ignore": ["node_modules"]
}Vite (vite.config.js):
export default defineConfig({
server: {
watch: {
ignored: ['**/node_modules/**'],
},
},
});Use a .watchmanconfig
If you use Watchman (used by Metro bundler in React Native, among others), create a .watchmanconfig in your project root:
{
"ignore_dirs": ["node_modules", ".git", "build", "dist"]
}VS Code: exclude folders from watching
Open VS Code settings (Ctrl+, or Cmd+,) and add to settings.json:
{
"files.watcherExclude": {
"**/node_modules/**": true,
"**/.git/objects/**": true,
"**/.git/subtree-cache/**": true,
"**/dist/**": true,
"**/build/**": true,
"**/coverage/**": true
}
}VS Code already excludes node_modules and .git by default in recent versions, but if you have other large generated directories (like dist, build, or coverage), adding them here helps.
Fix 4: macOS — Increase Open File Limits
On macOS, the EMFILE, too many open files error is caused by a low file descriptor limit, not inotify (which is Linux-only).
Check the current limit
ulimit -nIf the output is 256, that’s too low for most Node.js projects.
Increase the limit for the current shell session
ulimit -n 65536Then restart your dev server in the same terminal.
Make it permanent
Create or edit /Library/LaunchDaemons/limit.maxfiles.plist:
sudo tee /Library/LaunchDaemons/limit.maxfiles.plist <<EOF
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>limit.maxfiles</string>
<key>ProgramArguments</key>
<array>
<string>launchctl</string>
<string>limit</string>
<string>maxfiles</string>
<string>65536</string>
<string>200000</string>
</array>
<key>RunAtLoad</key>
<true/>
</dict>
</plist>
EOFLoad it:
sudo launchctl load -w /Library/LaunchDaemons/limit.maxfiles.plistYou can also add ulimit -n 65536 to your ~/.zshrc (or ~/.bashrc) so every new terminal session uses the higher limit.
Fix 5: WSL2-Specific Fix
WSL2 runs a real Linux kernel, so the inotify limit applies. However, WSL2 has a couple of quirks.
Increase the limit inside WSL2
The fix is the same as Linux:
sudo sysctl fs.inotify.max_user_watches=524288To make it persist across WSL restarts, add it to /etc/sysctl.conf or /etc/sysctl.d/ as described in Fix 2.
However, some older WSL2 kernel versions reset sysctl values when the WSL instance shuts down and restarts. If your setting doesn’t persist, add the sysctl command to your shell profile as a workaround:
# Add to ~/.bashrc or ~/.zshrc
if grep -q microsoft /proc/version 2>/dev/null; then
sudo sysctl -q fs.inotify.max_user_watches=524288 2>/dev/null
fiTo avoid the sudo password prompt, add a sudoers rule:
echo "$USER ALL=(root) NOPASSWD: $(which sysctl) fs.inotify.max_user_watches=524288" | sudo tee /etc/sudoers.d/inotifyStore your project files inside the WSL filesystem
If your project lives on the Windows filesystem (e.g., /mnt/c/Users/...), file watching is significantly slower and uses more resources due to the 9P filesystem bridge. Move your project into the native WSL2 filesystem (e.g., ~/projects/) for much better performance and fewer watcher issues.
Still Not Working?
Check for an actual disk space problem
ENOSPC can also mean you’ve genuinely run out of disk space — especially when the error message says no space left on device without mentioning “watchers.” Check your disk:
df -hIf a partition is at 100% usage, free up space. Common culprits:
# Clean up old Docker images and containers
docker system prune -a
# Clear npm cache
npm cache clean --force
# Clear systemd journal logs
sudo journalctl --vacuum-size=100MDocker containers inheriting host limits
Docker containers on Linux share the host kernel, including inotify limits. If you increased the limit on the host but your container still has the error, the container is reading the same /proc/sys/fs/inotify/max_user_watches value as the host. If your container is also running out of memory, see Fix: Docker Exited 137 OOMKilled.
Verify inside the container:
docker exec <container_name> cat /proc/sys/fs/inotify/max_user_watchesIf this shows the old value, increase the limit on the host (not inside the container) and restart the container. Containers cannot change sysctl values unless they run with --privileged or the correct --sysctl flag:
docker run --sysctl fs.inotify.max_user_watches=524288 your-imageFor Docker Compose:
services:
app:
sysctls:
- fs.inotify.max_user_watches=524288VS Code still showing the warning
If VS Code still shows “unable to watch for file changes” after increasing the limit:
- Reload VS Code (
Ctrl+Shift+P>Developer: Reload Window). - Check the limit took effect by running
cat /proc/sys/fs/inotify/max_user_watchesin the VS Code integrated terminal. - Exclude more directories from watching. Add large generated or vendored directories to
files.watcherExcludein your settings (see Fix 3). - Check VS Code’s file watcher by running
Ctrl+Shift+P>Developer: Show Logs> selectFile Watcherfrom the dropdown. This log shows exactly which paths VS Code is watching.
Systemd service limits
If the error occurs in a Node.js app running as a systemd service (not in your terminal), the service may have its own resource limits. Edit the service file:
sudo systemctl edit your-serviceAdd:
[Service]
LimitNOFILE=65536Then reload and restart:
sudo systemctl daemon-reload
sudo systemctl restart your-serviceThis sets the maximum number of open file descriptors for that specific service, independent of the system-wide inotify limit.
Related: Fix: Port 3000 Is Already in Use
Related Articles
Fix: ENOSPC: System limit for number of file watchers reached
How to fix the ENOSPC file watchers error on Linux by increasing the inotify watch limit, configuring VS Code, optimizing watched files, and handling Docker/WSL edge cases.
Fix: EACCES: permission denied, mkdir / open / unlink (Node.js)
How to fix EACCES permission denied errors in Node.js for mkdir, open, unlink, and scandir operations, covering npm global installs, Docker, NVM, CI/CD, and filesystem permissions.
Fix: SSL certificate problem: unable to get local issuer certificate
How to fix 'SSL certificate problem: unable to get local issuer certificate', 'CERT_HAS_EXPIRED', 'ERR_CERT_AUTHORITY_INVALID', and 'self signed certificate in certificate chain' errors in Git, curl, Node.js, Python, Docker, and more. Covers CA certificates, corporate proxies, Let's Encrypt, certificate chains, and self-signed certs.
Fix: EACCES permission denied when installing npm packages globally
How to fix 'Error: EACCES: permission denied, access /usr/local/lib/node_modules' when running npm install -g on macOS or Linux. Multiple solutions ranked by recommendation.