"Too many open files" on Linux: raise the right limit, or find the leak
Fix "Too many open files" (EMFILE): check a process's real limit in /proc, raise LimitNOFILE for systemd services, and tell a low limit from a file descriptor leak.
by OhSudo ··
Not sure this is your cause?Find it step by step: Disk full or out of memory →
Part of a learning path:Linux: from zero to fixing a server
A busy server starts failing with errors like these:
nginx: accept4() failed (24: Too many open files)java.io.IOException: Too many open filesError: EMFILE: too many open files, open '/srv/app/uploads/…'On Linux, almost everything a program works with is an open file: real files, but also every network connection, pipe and socket. Each process has a limit on how many it may hold at once — and on many systems the default is only 1024. A web server with a thousand clients hits that quickly.
There are two possibilities, and the fix is very different: the limit is too low for the work, or the program leaks — it opens files or connections and never closes them.
- A processfiles and connections it holds opencounted against
- Its limitoften 1024 (LimitNOFILE for services)reached(fails)
- Too many open filesEMFILE, error 24(breaks here)
TL;DR
pidof nginx # or: pgrep -f myappgrep 'open files' /proc/<PID>/limits # the limit the process really hassudo ls /proc/<PID>/fd | wc -l # how many it has open right nowsudo systemctl edit myapp # raise it for a service: LimitNOFILE=655351. Check the limit of the process — not of your shell
ulimit -nThis shows the limit of your shell — not of the service that fails. Services started by systemd don’t get their limits from your shell or from /etc/security/limits.conf. Ask the process itself:
grep 'open files' /proc/2481/limitsMax open files 1024 524288 filesThe first number is the soft limit (what the process gets), the second the hard limit (how far the process may raise it by itself). Now count what it actually uses:
sudo ls /proc/2481/fd | wc -lClose to the soft limit → it’s the cause.
2. A limit too low: raise it
For a systemd service (nginx, your app, a database): add a drop-in.
sudo systemctl edit myapp[Service]LimitNOFILE=65535sudo systemctl restart myappgrep 'open files' /proc/$(systemctl show -p MainPID --value myapp)/limits/etc/security/limits.conf does not apply to services — it’s read only for login sessions (SSH, console, su). Many guides change it, see no effect, and stop there.
For programs you start from a shell: limits.conf is the right place, and it takes effect at the next login.
guest soft nofile 65535guest hard nofile 65535nginx also has its own setting: worker_rlimit_nofile 65535; in the main context of nginx.conf, and each worker needs about two files per proxied connection (client + upstream), so keep worker_connections below that.
In Docker: docker run --ulimit nofile=65535:65535 …, or in Compose:
services: app: ulimits: nofile: soft: 65535 hard: 655353. A leak: raising the limit only delays it
If the count from section 1 keeps growing under steady traffic and never comes back down, the program forgets to close something. A higher limit just moves the crash further away. See what it holds:
sudo ls -l /proc/2481/fd | awk '{print $NF}' | sed 's/:\[.*//' | sort | uniq -c | sort -rn | head 9812 socket 41 /srv/app/logs/app.log 12 pipeThousands of socket entries point to connections that are never closed — often HTTP clients or database connections created per request instead of reused. Connections the other side already closed show up as CLOSE_WAIT:
ss -tanp | grep -c CLOSE_WAITA large number there is the program’s bug: it should close those sockets. The same file listed thousands of times means it opens it again and again without closing it.
4. The whole system
Very rarely, the limit for the entire system is reached, and the kernel says so in dmesg: VFS: file-max limit 1048576 reached. Check:
cat /proc/sys/fs/file-nr # open, unused, maximumOn current systems the maximum is huge, so if you get here, look for a leak first.
Shell, we have a problem!
Similar, but different: inotify cannot be used, reverting to polling: Too many open files (tail -f, file watchers in Node.js or IDEs) is about inotify instances, not file descriptors: raise fs.inotify.max_user_instances with sysctl. ENOSPC: System limit for number of file watchers reached is the related fs.inotify.max_user_watches. MySQL’s Too many connections is a database setting — see MySQL ERROR 1040. The same kind of limit for processes is fork: Resource temporarily unavailable.
Found this useful? Share it.
Found a mistake? Let us know at contact@ohsudo.com.