lenec ru

← все посты

Error: ENOSPC inotify watch limit — что делать

19K

Запускаешь dev-сервер большого проекта, и через секунду в консоли:

Error: ENOSPC: System limit for number of file watchers reached, watch '/path/to/project'

Скажу честно: к самой ENOSPC (no space) это отношения не имеет. Места на диске у тебя полно. Просто Linux считает inotify watcher'ы — лимитированный системный ресурс — и ENOSPC выдаёт, когда он закончился. Сообщение мне всегда казалось обманчивым.

Проблема обычно встречается на больших монорепах, у Vite/Next/Webpack-проектов с тысячами файлов в node_modules. На macOS и Windows другие механизмы файловых вотчеров, поэтому ошибка только на Linux (и WSL).

Что такое inotify и почему он кончается

Inotify — это механизм Linux, который сообщает программам об изменениях в файловой системе. Каждый «слежкаемый» файл или директория — это watch. У ядра есть три параметра:

  • fs.inotify.max_user_watches — сколько вотчей может держать один пользователь;
  • fs.inotify.max_user_instances — сколько экземпляров inotify;
  • fs.inotify.max_queued_events — глубина очереди.

Дефолты на разных дистрибутивах разные, но часто это 8192 или 65536. Если у тебя в проекте больше файлов, чем лимит, dev-сервер тянет на каждый по watch и упирается.

Самая быстрая починка

Текущий лимит:

cat /proc/sys/fs/inotify/max_user_watches

Поднять без перезагрузки:

sudo sysctl fs.inotify.max_user_watches=524288

Чтобы значение пережило ребут, добавляешь его в sysctl-конфиг:

echo 'fs.inotify.max_user_watches=524288' | sudo tee /etc/sysctl.d/99-inotify.conf
sudo sysctl -p /etc/sysctl.d/99-inotify.conf

524288 — стандартное значение, которое советует большинство FAQ и которое выдержит даже большую монорепу. Можно ставить и меньше, если памяти у машины немного: каждый watcher — это около 1 КБ kernel memory. На 524288 это полгигабайта в худшем случае.

А почему сразу так много

Vite, Next в dev-режиме, Nodemon — все они вешают вотчи на исходники, на конфиги, на node_modules (в случае Vite — выборочно). Дополнительно у тебя в редакторе работает file watcher, индексер у IDE, иногда антивирус или утилита синхронизации. Каждая из этих программ ест из общего пула.

На свежем ноутбуке с одним проектом 8192 хватает. На рабочей машине с 5 параллельными монорепами и WebStorm в фоне — улетает мгновенно.

Кто ест больше всего

Если интересно, кто конкретно держит вотчеры, есть скрипт, который пробежится по всем процессам:

find /proc/*/fd -lname anon_inode:inotify 2>/dev/null \
  | sed 's|/proc/\([0-9]*\)/fd/.*|\1|' | sort -u \
  | xargs -r ps -p

Список процессов, которые держат хотя бы один inotify-instance. Дальше можно для каждого процесса посчитать число вотчей через /proc/$pid/fdinfo/ — но обычно достаточно понять, кто съедает (часто это твой IDE или Webpack).

Альтернативное решение: polling

Если не хочется (или нельзя) править системные параметры — можно переключить файловые вотчеры на режим polling. В этом случае инструмент сам опрашивает файлы по таймеру, не используя inotify. Нагрузка на CPU и батарею выше, зато ENOSPC исчезает.

В vite.config.js:

export default {
  server: {
    watch: {
      usePolling: true,
      interval: 300,
    },
  },
};

В nodemon.json:

{
  "legacyWatch": true
}

В webpack:

module.exports = {
  watchOptions: {
    poll: 1000,
  },
};

На Docker-контейнерах с пробросом тома polling часто и так нужен — inotify туда не передаётся между хостом и контейнером.

Особый случай: WSL2

На WSL2 у пользователя свои значения fs.inotify.*, прописываются точно так же через /etc/sysctl.d/. Но! Если редактируешь файлы в Windows и они подмонтированы в WSL через /mnt/c/, события об изменениях из inotify не приходят вообще. Это ограничение DrvFS, и его не лечит ни один лимит. Нужно либо хранить проект внутри WSL-файловой системы (~/projects/..., не /mnt/c/...), либо включать polling.

Если поднял лимит — сразу проверь

cat /proc/sys/fs/inotify/max_user_watches
sysctl fs.inotify.max_user_instances

Иногда люди забывают про max_user_instances, поднимают только max_user_watches, а ENOSPC возвращается через неделю. Подними и его в разумных пределах:

echo 'fs.inotify.max_user_instances=512' | sudo tee -a /etc/sysctl.d/99-inotify.conf
sudo sysctl -p /etc/sysctl.d/99-inotify.conf

Что делаю на каждой новой Linux-машине

Я уже несколько лет первым делом, когда раскатываю Linux под разработку, пишу в /etc/sysctl.d/99-inotify.conf:

fs.inotify.max_user_watches=524288
fs.inotify.max_user_instances=512

Применяю — и больше не возвращаюсь. На рабочих серверах эти лимиты обычно не нужны (там не запускается dev-сервер), а на машине разработчика это обязательная часть начальной настройки наравне с git и nvm.

Чек-лист

  • Понять, действительно ли это лимит inotify (а не реальная нехватка места — на всякий случай df -h).
  • Поднять fs.inotify.max_user_watches до 524288.
  • Поднять fs.inotify.max_user_instances до 256–512.
  • В Docker и WSL — рассмотреть polling.
  • Закрепить через файл в /etc/sysctl.d/.

Это разовое действие на пять минут, после которого dev-сервер перестаёт капризничать на больших проектах. Сообщение «ENOSPC» вводит в заблуждение, но решение всегда одно и то же.

Комментарии 0

  • Будьте первым, кто оставит комментарий.

Войдите, чтобы оставить комментарий.