Skip to content
ohsudo, Home
Linux

"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.

Intermediate3 min readApplies to Ubuntu · Debian · RHEL / Rocky / AlmaLinux · systemd · Docker

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 files
Error: 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.

  1. A processfiles and connections it holds open
  2. Its limitoften 1024 (LimitNOFILE for services)
  3. Too many open filesEMFILE, error 24(breaks here)
Files, connections, pipes and sockets all count as open files, and each process has a limit, often 1024. Either the limit is too low for the work, or the program leaks them.

TL;DR

Terminal window
pidof nginx # or: pgrep -f myapp
grep 'open files' /proc/<PID>/limits # the limit the process really has
sudo ls /proc/<PID>/fd | wc -l # how many it has open right now
sudo systemctl edit myapp # raise it for a service: LimitNOFILE=65535

1. Check the limit of the process — not of your shell

Terminal window
ulimit -n

This 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:

Terminal window
grep 'open files' /proc/2481/limits
Max open files 1024 524288 files

The 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:

Terminal window
sudo ls /proc/2481/fd | wc -l

Close 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.

Terminal window
sudo systemctl edit myapp
[Service]
LimitNOFILE=65535
Terminal window
sudo systemctl restart myapp
grep '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.

/etc/security/limits.conf
guest soft nofile 65535
guest hard nofile 65535

nginx 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: 65535

3. 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:

Terminal window
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 pipe

Thousands 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:

Terminal window
ss -tanp | grep -c CLOSE_WAIT

A 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:

Terminal window
cat /proc/sys/fs/file-nr # open, unused, maximum

On 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.

Tools

Try it yourself

Articles

Related articles