Skip to content
Commitpedia
Log in Join & edit

Fix: too many open files

A process hit its file descriptor limit, usually 1024. Raise it for the shell, the systemd unit or the user, fix a descriptor leak, or raise the inotify watch limits when the message comes from a file watcher.

Drafted with AI from official documentation. Scripts were run in a test environment and repository links verified. Awaiting a human check. Did it work for you? Last edited Outdated?

Edit history of Fix: too many open files: 1 recorded edit
Edit history · 1 edit
Type
Article
Edits
1
Editors
1
First issued
15 Oct 2026
Last edit
15 Oct 2026
Reading
4 min
Error: EMFILE: too many open files, open '/app/public/index.html'
OSError: [Errno 24] Too many open files: 'data/part-0931.csv'
accept: too many open files
nginx: [alert] socket() failed (24: Too many open files)
ENOSPC: System limit for number of file watchers reached
tail: inotify cannot be used, reverting to polling: Too many open files

Every open file, socket, pipe and directory listing costs a file descriptor, and each process has a limit on how many it may hold at once. Most Linux distributions default to 1024 per process (the soft limit), which a busy web server, database or build tool exhausts quickly. There is also a system-wide limit, and a separate limit for inotify watches that file-watching tools hit.

Step 1: see which limit you hit and who is using them

Check before you run this

  • Runs with administrator rights. Make sure you understand every line.
ulimit -n                      # soft limit for this shell and its children
ulimit -Hn                     # hard limit, the most a user may raise it to

# For a running process
cat /proc/48213/limits | grep 'open files'
ls /proc/48213/fd | wc -l      # how many it has open right now
sudo lsof -p 48213 | awk '{print $5}' | sort | uniq -c | sort -rn | head   # by type: REG, IPv4, unix, ...

# System-wide
cat /proc/sys/fs/file-nr       # allocated, free, maximum
sysctl fs.file-max

Cause 1: the per-process limit is simply too low

For the current shell session, raise the soft limit up to the hard limit. This is enough for a one-off command or a build.

ulimit -n 65536
npm run build          # or whatever failed

For login sessions, set the limit in /etc/security/limits.conf or a file in /etc/security/limits.d/; it applies after the next login.

# /etc/security/limits.d/90-nofile.conf
*        soft    nofile    65536
*        hard    nofile    524288
appuser  soft    nofile    262144
appuser  hard    nofile    524288

Cause 2: a systemd service ignores limits.conf

Services started by systemd do not go through PAM, so limits.conf has no effect on them. Set the limit in the unit.

Check before you run this

  • Runs with administrator rights. Make sure you understand every line.
sudo systemctl edit nginx.service
# add:
[Service]
LimitNOFILE=65536

sudo systemctl daemon-reload
sudo systemctl restart nginx.service
cat /proc/$(systemctl show -p MainPID --value nginx.service)/limits | grep 'open files'

Some daemons have their own setting on top: nginx worker_rlimit_nofile 65536; in nginx.conf, PostgreSQL max_files_per_process, MySQL open_files_limit, Elasticsearch requires 65536 and refuses to start below it. Docker containers inherit the daemon’s default; set --ulimit nofile=65536:65536 on docker run or ulimits: in Compose.

Cause 3: the application leaks descriptors

If ls /proc/PID/fd | wc -l grows steadily while traffic is flat, the program opens files or connections and never closes them. Raising the limit only delays the crash. Look at what the descriptors are: hundreds of the same log file means a logger opened per request; thousands of sockets in CLOSE_WAIT (ss -tanp | grep CLOSE-WAIT) means HTTP responses are not consumed or closed. Use with open(...) in Python, try/finally with close(), connection pools with limits, and stream.destroy() in Node.

Cause 4: inotify watches, not file descriptors

Webpack, Vite, nodemon, VS Code, tail -f, Syncthing and IDE indexers watch directories with inotify. The kernel limits watches per user, and the error says ENOSPC or mentions watchers even though no disk is full. Raise the limits and persist them.

Check before you run this

  • Runs with administrator rights. Make sure you understand every line.
sysctl fs.inotify.max_user_watches fs.inotify.max_user_instances

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

# Persist
echo 'fs.inotify.max_user_watches=524288' | sudo tee /etc/sysctl.d/90-inotify.conf
echo 'fs.inotify.max_user_instances=512' | sudo tee -a /etc/sysctl.d/90-inotify.conf
sudo sysctl --system

# Who uses the watches
find /proc/*/fd -lname 'anon_inode:inotify' -printf '%h\n' 2>/dev/null | cut -d/ -f3 | sort | uniq -c | sort -rn | head

Also exclude node_modules, .git and build output from the watcher’s configuration; a watcher that follows a 200,000-file dependency tree is the usual reason the default is not enough.

Check that it is fixed

ulimit -n                                    # new shell shows the new value
cat /proc/PID/limits | grep 'open files'     # the service shows LimitNOFILE
watch -n5 'ls /proc/PID/fd | wc -l'          # stable, not climbing

When it is not what you think

  • ENFILE (Too many open files in system) is the system-wide limit fs.file-max, hit only when the whole machine is in trouble, often because one process leaked millions.
  • ENOSPC: no space left on device from a file watcher is the inotify limit (Cause 4), not a full disk; df -h will look fine.
  • On macOS the default soft limit is 256; ulimit -n 65536 works per shell, and launchctl limit maxfiles shows the system values. Node and Docker Desktop hit this on large projects.
  • A hard limit you cannot raise as a normal user (ulimit -Hn small) must be raised by root in limits.conf or via systemd’s DefaultLimitNOFILE in /etc/systemd/system.conf and user.conf.

Official documentation

Did this work for you?

No votes yet. Be the first.

If it did not work, the report form below tells the editors what went wrong.

See also

  • 0061 Fix: Address already in use (free a busy port) Your server cannot start because another process already listens on its port. This script shows which process holds the port and stops… Intermediate · Fixes an error · Linux, macOS Script Processes & ports · Shell scripting 15 Oct 2026
  • 0164 systemd services: systemctl and journalctl basics systemd starts and supervises services on most Linux servers. systemctl starts, stops and enables them; journalctl shows their logs. Beginner · Explains an idea · Linux Article Services & systemd 15 Oct 2026
  • 0165 Write a systemd service unit for your own app Turn any long-running program into a proper service: create a unit file, run it as an unprivileged user, restart it on failure… Intermediate · Step by step · Linux Article Services & systemd 15 Oct 2026
  • 0166 Replace a cron job with a systemd timer A systemd timer runs a service on a schedule like cron, but logs every run to the journal, can catch up missed… Intermediate · Step by step · Linux Article Services & systemd 15 Oct 2026
  • 0167 Fix: Job for nginx.service failed because the control process exited with error code systemctl prints this when a service's start command exits with an error. The real reason is in journalctl; for nginx it is… Intermediate · Fixes an error · Linux Article Networking & firewalls · Services & systemd 15 Oct 2026
  • 0168 Server health check script: disk, memory and failed units A dependency-free bash script that checks disk and inode usage, available memory, load, failed systemd units and pending reboots, and exits non-zero… Intermediate · Cheat sheet · Linux Script Disks, LVM & filesystems · Services & systemd 15 Oct 2026

Repos in the wild

History

Every saved edit is kept. The plot on the sleeve draws one line per edit. Open any edit to see exactly what changed.

  1. Dominik +5,296 chars

Report a problem

Something wrong, unsafe or copied? Tell the editors.
What is wrong?