Tình huống gặp lỗi
Chạy npm start hoặc npm run dev rồi bị crash với thông báo:
Error: ENOSPC: System limit for number of file watchers reached, watch '/path/to/project'
at FSWatcher. (/project/node_modules/chokidar/lib/fsevents-handler.js:180:19)
Linux có giới hạn ở cấp kernel về số lượng file và thư mục có thể theo dõi đồng thời thông qua inotify. Khi kết hợp node_modules (có thể chứa hơn 50.000 file trong một dự án hiện đại), cây thư mục nguồn, và các tiến trình khác như VSCode hay Dropbox — bạn đã vượt quá giới hạn đó.
Các nguyên nhân thường gặp: khởi động webpack dev server, chạy nodemon, mở một monorepo lớn trong VSCode, hoặc khởi chạy nhiều dev server cùng lúc.
Debug: xác nhận đây là lỗi giới hạn inotify
Kiểm tra giới hạn hiện tại và mức sử dụng:
# Số watcher tối đa hiện tại
cat /proc/sys/fs/inotify/max_user_watches
# Số instance được phép
cat /proc/sys/fs/inotify/max_user_instances
# Xem tiến trình nào đang tiêu tốn watch
find /proc/*/fd -lname anon_inode:inotify 2>/dev/null | \
awk -F/ '{print $3}' | xargs -I{} sh -c 'echo -n "{}: "; cat /proc/{}/cmdline | tr "\0" " "; echo'
Một cài đặt Linux mặc định chỉ đặt max_user_watches là 8192. Đó chính là nguyên nhân. Một dự án Next.js hoặc CRA cỡ trung bình có thể ngốn từ 8.000 đến 15.000 watcher — riêng node_modules đã chiếm phần lớn con số đó.
Sửa tạm thời (mất sau khi khởi động lại)
sudo sysctl fs.inotify.max_user_watches=524288
Khởi động lại dev server ngay sau đó. Nếu server chạy bình thường, cách sửa này có tác dụng — nhưng sẽ mất sau khi reboot. Hãy làm cho nó vĩnh viễn ở bước tiếp theo.
Sửa vĩnh viễn
Ghi giá trị vào sysctl.conf:
echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf
sudo sysctl -p
Trên Ubuntu 20.04+ và Debian, cách gọn hơn là tạo một file config riêng:
echo 'fs.inotify.max_user_watches=524288' | sudo tee /etc/sysctl.d/99-inotify-watches.conf
sudo sysctl --system
Cả hai cách đều hoạt động. Giá trị 524288 (~512K) là chuẩn cộng đồng — tài liệu webpack, các issue của Next.js, và nhiều năm câu trả lời trên Stack Overflow đều đồng thuận ở con số này. Đang dùng monorepo hoặc mở nhiều dự án cùng lúc? Hãy nhân đôi lên:
# Dành cho monorepo hoặc nhiều dự án mở cùng lúc
echo 'fs.inotify.max_user_watches=1048576' | sudo tee /etc/sysctl.d/99-inotify-watches.conf
sudo sysctl --system
Kiểm tra sau khi sửa
# Xác nhận giá trị mới đã được áp dụng
cat /proc/sys/fs/inotify/max_user_watches
# Kết quả phải là: 524288
Khởi động lại dev server. Server sẽ chạy bình thường. Đang dùng WSL2? Còn một bước nữa.
Lưu ý cho WSL2
WSL2 không áp dụng thay đổi từ sysctl.conf khi khởi động theo cách giống Linux thông thường. Có hai lựa chọn:
Thêm lệnh khởi động vào /etc/wsl.conf (khuyến nghị):
[boot]
command = sysctl -w fs.inotify.max_user_watches=524288
Hoặc đặt trong shell profile như một phương án dự phòng:
# Trong ~/.bashrc hoặc ~/.zshrc của bạn
if [ -f /proc/sys/fs/inotify/max_user_watches ]; then
sudo sysctl -w fs.inotify.max_user_watches=524288 > /dev/null 2>&1
fi
Cách dùng wsl.conf gọn hơn — hãy dùng cách đó.
Mẹo thêm: giảm số watcher thay vì tăng giới hạn
Không có quyền root? Trên server dùng chung hoặc container có quyền hạn chế, hãy thu gọn những gì cần theo dõi:
- Thêm
node_modulesvào danh sách ignore trong.watchmanconfignếu đang dùng Watchman - Trong webpack, đặt
watchOptions.ignored: /node_modules/ - Trong Vite, cấu hình
server.watch.ignored - Trong VSCode, thêm
node_modulesvà các thư mục build vàofiles.watcherExcludetrong settings
// vite.config.ts
export default defineConfig({
server: {
watch: {
ignored: ['**/node_modules/**', '**/dist/**']
}
}
})
// webpack.config.js
module.exports = {
watchOptions: {
ignored: /node_modules/,
}
}
Bài học rút ra
- Giới hạn mặc định
8192có từ trước thời npm — hãy tăng nó trên mọi máy dev Linux ngay khi cài đặt, trước khi gặp lỗi này - Các dự án lớn cộng dồn rất nhanh: editor + dev server + test watcher có thể mỗi thứ tiêu tốn hàng nghìn watch cùng lúc
- Riêng VSCode đã ngốn hàng nghìn watcher trên một repo lớn — kiểm tra
files.watcherExcludetrong settings nếu bạn liên tục gặp lỗi này - Các Docker container kế thừa giới hạn inotify từ host — hãy sửa trên host, không phải bên trong container
- Mỗi watcher tốn khoảng 1KB bộ nhớ kernel; tăng lên 524288 dùng tối đa ~512MB, nhưng trên thực tế ít hơn nhiều

