状況
npm start または npm run dev を実行すると、以下のエラーで落ちる:
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には、inotifyを通じて同時に監視できるファイルやディレクトリの数にカーネルレベルの上限がある。現代のプロジェクトでは node_modules だけで50,000以上のファイルが含まれることがあり、ソースツリーやVSCode・Dropboxなどの他プロセスも加わると、あっという間に上限を超えてしまう。
よくあるトリガー:webpackのdevサーバー起動、nodemon の実行、大規模なモノレポをVSCodeで開く、複数のdevサーバーを同時に起動するなど。
デバッグ:inotifyの上限かどうか確認する
現在の上限と使用状況を確認する:
# 現在のウォッチャー最大数
cat /proc/sys/fs/inotify/max_user_watches
# 許可されているインスタンス数
cat /proc/sys/fs/inotify/max_user_instances
# ウォッチャーを消費しているプロセスを確認
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'
Linuxのデフォルトインストールでは max_user_watches はわずか 8192 に設定されている。これが原因だ。中規模のNext.jsやCRAプロジェクトだけで8,000〜15,000ウォッチャーを消費することがあり、その大半は node_modules によるものだ。
即時対処法(一時的、再起動で元に戻る)
sudo sysctl fs.inotify.max_user_watches=524288
直後にdevサーバーを起動してみる。正常に起動すれば修正成功だが、再起動すると元に戻る。次は永続的な設定を行う。
永続的な修正方法
sysctl.conf に値を書き込む:
echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf
sudo sysctl -p
Ubuntu 20.04以降とDebianでは、専用の設定ファイルを使うほうがスマートだ:
echo 'fs.inotify.max_user_watches=524288' | sudo tee /etc/sysctl.d/99-inotify-watches.conf
sudo sysctl --system
どちらでも問題ない。524288(約512K)はコミュニティの標準値であり、webpackのドキュメント、Next.jsのIssue、Stack Overflowの回答でも一致している。モノレポや複数プロジェクトを同時に扱う場合は2倍にする:
# モノレポや複数プロジェクトを同時に開く場合
echo 'fs.inotify.max_user_watches=1048576' | sudo tee /etc/sysctl.d/99-inotify-watches.conf
sudo sysctl --system
修正の確認
# 新しい値が適用されているか確認
cat /proc/sys/fs/inotify/max_user_watches
# 出力されるべき値: 524288
devサーバーを再起動する。正常に起動するはずだ。WSL2を使っている場合は、もう一手順必要だ。
WSL2に関する注意
WSL2では、ネイティブLinuxと同じ方法で起動時に sysctl.conf の変更が適用されない。2つの対処法がある:
/etc/wsl.conf に起動コマンドを追加する(推奨):
[boot]
command = sysctl -w fs.inotify.max_user_watches=524288
またはシェルのプロファイルにフォールバックとして設定する:
# ~/.bashrc または ~/.zshrc に追記
if [ -f /proc/sys/fs/inotify/max_user_watches ]; then
sudo sysctl -w fs.inotify.max_user_watches=524288 > /dev/null 2>&1
fi
wsl.conf を使う方法がよりクリーンなのでそちらを推奨する。
補足:上限を上げる代わりにウォッチャー使用数を減らす
root権限がない場合や、権限が制限された共有サーバー・コンテナ上では、監視対象を絞る方法もある:
- Watchmanを使用している場合は、
.watchmanconfigの無視リストにnode_modulesを追加する - webpackでは
watchOptions.ignored: /node_modules/を設定する - Viteでは
server.watch.ignoredを設定する - VSCodeでは、設定の
files.watcherExcludeにnode_modulesやビルドフォルダを追加する
// vite.config.ts
export default defineConfig({
server: {
watch: {
ignored: ['**/node_modules/**', '**/dist/**']
}
}
})
// webpack.config.js
module.exports = {
watchOptions: {
ignored: /node_modules/,
}
}
まとめ・教訓
- デフォルトの
8192という上限はnpm登場以前に設定されたもの。Linuxの開発マシンをセットアップする際は、エラーに遭遇する前に必ず引き上げておくこと - 大規模プロジェクトでは積み上がりが早い:エディタ+devサーバー+テストウォッチャーがそれぞれ数千のウォッチャーを同時に消費することがある
- VSCodeだけで大きなリポジトリの場合に数千のウォッチャーを消費する。繰り返しこのエラーに遭遇するなら、設定の
files.watcherExcludeを確認すること - Dockerコンテナはホストのinotify上限を引き継ぐ。コンテナ内ではなく、ホスト側で修正すること
- ウォッチャー1つあたり約1KBのカーネルメモリを消費する。524288に引き上げても最大約512MBであり、実際にはそれより大幅に少ない

