How to Fix ENOSPC: System Limit for Number of File Watchers Reached
On this page
You're running your Next.js dev server, Webpack build, or Jest tests, and suddenly everything stops with a cryptic error: ENOSPC: System limit for number of file watchers reached. Your project isn't broken. Your code is fine. The problem is that your operating system ran out of file descriptor capacity to monitor your project's files.
TL;DR: Fix the ENOSPC file watcher limit error in Node.js and development tools. Learn why it happens and permanent solutions for Linux systems.
This is one of those errors that feels mysterious until you understand what's happening under the hood. I'll walk you through the root cause, show you the fixes, and explain why each one works.
What Is ENOSPC and Why Does It Happen?
ENOSPC stands for "Error NO Space" — but it's misleading. You likely have plenty of disk space. The real issue is the fs.watch() and fs.watchFile() mechanisms that Node.js uses for file monitoring.
On Linux systems, file watching is handled through the inotify kernel subsystem. When your bundler, test runner, or development server watches your project for changes, it creates an inotify "watch" for each file and directory. Linux has a kernel limit on how many active watches can exist simultaneously across the entire system.
Here's what typically triggers it:
- Large monorepos with thousands of files
- Node_modules directories with massive dependency trees
- Multiple dev servers or build processes running simultaneously
- Docker containers with aggressive file watching enabled
- WSL2 on Windows with particularly tight default limits
The default limit on most Linux distributions is around 8,192 watches. A typical node_modules folder in a modern project can easily consume 20,000+ watches across all its nested dependencies.
Check Your Current Limit
Before applying any fix, see what your system is actually set to:
cat /proc/sys/fs/inotify/max_user_watches
This shows the per-user limit. If your project is consuming more watches than this number, you'll hit the ENOSPC error.
You can also see active watches:
find /proc/*/fd -lname 'anon_inode:inotify' 2>/dev/null | wc -l
This counts all active inotify file descriptors across your entire system.
Solution 1: Increase the inotify Limit (Permanent Fix)
This is the recommended solution for development machines. You're increasing the kernel limit to accommodate modern projects.
Edit the sysctl configuration:
sudo nano /etc/sysctl.d/99-custom.conf
Add or update this line:
fs.inotify.max_user_watches=524288
Then apply the change immediately:
sudo sysctl -p /etc/sysctl.d/99-custom.conf
Verify it took effect:
cat /proc/sys/fs/inotify/max_user_watches
The value 524288 (512KB) is generous enough for even large monorepos while being reasonable for system resources. You can adjust it lower if needed, but I don't recommend going below 262144 for modern development.
Why 524288?
At roughly one 32-byte inotify structure per watch, this consumes minimal memory — around 16-20MB of kernel memory. The tradeoff is excellent for development machines.
Solution 2: Exclude Directories from Watching
If you can't or don't want to increase system limits, reduce what you're watching. This is practical when you know certain directories don't need monitoring.
For Create React App projects:
Create a .env file in your project root:
WATCHPACK_POLL=false
EXTEND_ESLINT=true
For Next.js projects:
Update your next.config.js:
/** @type {import('next').NextConfig} */
const nextConfig = {
watchOptions: {
poll: false,
ignored: ['**/node_modules', '**/.next', '**/dist', '**/.git'],
},
};
module.exports = nextConfig;
For webpack projects:
In your webpack.config.js:
module.exports = {
mode: 'development',
watch: true,
watchOptions: {
ignored: /node_modules|\.git/,
aggregateTimeout: 300,
poll: false,
},
// rest of config...
};
For Jest:
Update your jest.config.js:
module.exports = {
testEnvironment: 'node',
watchPathIgnorePatterns: [
'<rootDir>/node_modules/',
'<rootDir>/.git/',
'<rootDir>/dist/',
'<rootDir>/build/',
],
};
The downside here is that changes in excluded directories won't trigger rebuilds. Use this approach selectively — only exclude directories you know won't change during development.
Solution 3: Use Polling Instead of inotify
For Docker containers or situations where you can't modify system limits, switch to polling-based file watching. It's less efficient but doesn't hit inotify limits.
In webpack:
module.exports = {
watch: true,
watchOptions: {
poll: 1000, // Check for changes every 1000ms
aggregateTimeout: 300,
},
};
In Next.js:
/** @type {import('next').NextConfig} */
const nextConfig = {
watchOptions: {
poll: 1000,
aggregateTimeout: 300,
},
};
module.exports = nextConfig;
Important: Polling trade-offs
Polling increases CPU usage and makes hot reloads slightly slower. It's a viable workaround but not ideal for regular development. The poll value is in milliseconds — higher values reduce CPU but increase the delay before changes are detected. I'd recommend starting at 1000 and adjusting down if responsiveness is critical.
Solution 4: For Docker Containers
If you're running Node.js in Docker and hitting this limit, increase the inotify limits when starting the container:
docker run \
--sysctl fs.inotify.max_user_watches=524288 \
--sysctl fs.inotify.max_queued_events=32768 \
-it your-node-app
Or in docker-compose.yml:
services:
app:
build: .
sysctls:
- fs.inotify.max_user_watches=524288
- fs.inotify.max_queued_events=32768
volumes:
- .:/app
- /app/node_modules
command: npm run dev
The max_queued_events setting prevents inotify event queue overflow when many files change simultaneously.
Solution 5: For WSL2 on Windows
WSL2 shares system limits between Windows and Linux. If you hit ENOSPC in WSL2, edit the WSL configuration on the Windows side:
Create or edit %USERPROFILE%\.wslconfig:
[interop]
appendWindowsPath = true
[interop]
enabled = true
[wsl2]
kernelCommandLine = inotify.max_user_watches=524288
Then restart WSL2:
wsl --shutdown
And restart your WSL2 distribution. This passes the kernel parameter directly to the WSL2 VM.
Practical Recommendations
For local development machines: Use Solution 1 (increase the system limit). It's permanent, requires one setup, and solves the problem once and for all.
For Docker containers: Use Solution 4. Container-level sysctl settings are cleaner than modifying host systems.
For monorepos with extremely large node_modules: Combine Solution 1 with selective exclusions (Solution 2). Watch everything you care about, but explicitly exclude vendor directories you know are stable.
For CI/CD pipelines: Use Solution 2 or 3. Polling is acceptable in CI since you're not iterating in real-time, and it avoids the need for system-level configuration changes across different machines.
For WSL2 developers: Use Solution 5. It's Windows-native and doesn't interfere with your Linux environment.
Verifying Your Fix
After applying any solution, restart your dev server or build process:
npm run dev
# or
yarn dev
# or
npm test -- --watch
If the error is gone, you're all set. If you're still seeing ENOSPC, verify your changes took effect:
cat /proc/sys/fs/inotify/max_user_watches
And make sure you're not running multiple watch processes that cumulatively exceed your limit. Sometimes the issue is quantity, not a configuration mistake.
Summary
The ENOSPC error is a symptom of modern development workflows — our projects are larger and more complex than the default Linux kernel limits were designed for. The fix is straightforward: either increase the limits (recommended) or reduce what you're watching.
For most developers, increasing fs.inotify.max_user_watches to 524288 is a one-time setup that eliminates the problem permanently. For containerized development, handle it at the container level. And if you need more granular control, selectively exclude directories you know are stable.
Choose the solution that matches your development environment, apply it, and get back to shipping.
Sources
Looking for more? Check out Adaptels.
Related Articles
How to Debug Node.js Memory Leaks (Step-by-Step Guide)
Learn how to detect, diagnose, and fix Node.js memory leaks using heap snapshots, Chrome DevTools, and clinic.js — with real code examples.
How to Set Up GitHub Actions for CI/CD (Beginner-Friendly Guide)
Learn how to set up GitHub Actions for CI/CD pipelines — from your first workflow file to automated deployments with real YAML examples.
Running Local LLMs With Ollama: Developer Setup Guide
Set up Ollama to run local LLMs on your machine. Covers installation, model selection, API usage, and integrating local models into your dev workflow.