How to diagnose “Too many open files” on Linux
Treat the limit as evidence, not merely an obstacle: identify which process ran out of descriptors, inspect what it has open, and change limits only after you understand the workload.
Reviewed by the Terminaster editorial team · Updated
What you will take away
- “Too many open files” usually means a process reached its file-descriptor limit, not that the filesystem contains too many files.
- Compare the process’s descriptor count with its soft and hard RLIMIT_NOFILE values before changing configuration.
- Classify the open descriptors—files, sockets, pipes, or deleted files—to distinguish legitimate load from a resource leak.
- Raise limits at the process supervisor and fix the leak; changing one shell does not repair an already-running service.
Start by identifying which limit was exhausted
On Linux, open files are represented inside a process by small integer file descriptors. Regular files, network sockets, pipes, event notification objects, and several other kernel resources all consume descriptor numbers, so a server can hit the limit without opening many ordinary files.
The common EMFILE error means one process has reached its RLIMIT_NOFILE limit. The less common ENFILE error means the kernel could not allocate another system-wide open-file structure. Capture the exact error and the affected process before assuming which condition occurred.
Inspect limits in the current shell and a running process
ulimit -Sn
ulimit -Hn
pid=1234
cat "/proc/$pid/limits" | grep -F 'Max open files'
ls -1 "/proc/$pid/fd" 2>/dev/null | wc -lInspect what the process actually has open
A descriptor count close to the soft limit confirms immediate pressure, but the shape of the descriptor set explains why. Repeated sockets to one endpoint can indicate missing connection cleanup; many copies of one pathname can indicate a file leak; a balanced mix may be normal for a busy proxy or database.
The symbolic links under /proc/PID/fd show each descriptor’s target. Classify those targets into a few stable categories first; listing individual targets is useful for investigation but is only a best-effort display because a pathname itself can contain a newline.
- Take two or more snapshots during steady traffic; a count that only grows is more suspicious than a high but stable count.
- Correlate growth with request rate, active connections, worker count, and deployment time.
- Check for descriptors whose targets end in “(deleted),” which can also explain unexpectedly high disk usage.
- Do not close or overwrite entries through /proc/PID/fd as an improvised fix; the application owns their lifecycle.
Classify descriptors without parsing pathnames as lines
pid=1234
find "/proc/$pid/fd" -mindepth 1 -maxdepth 1 -printf '%l\0' 2>/dev/null \
| while IFS= read -r -d '' target; do
case "$target" in
socket:\[*\]) printf 'socket\n' ;;
pipe:\[*\]) printf 'pipe\n' ;;
anon_inode:\[*\]) printf 'anon_inode\n' ;;
*' (deleted)') printf 'deleted\n' ;;
/*) printf 'filesystem\n' ;;
*) printf 'other\n' ;;
esac
done \
| sort | uniq -c | sort -nr
# Best-effort human display of descriptor numbers and targets
ls -l "/proc/$pid/fd" 2>/dev/null | head -40Separate a per-process shortage from system-wide pressure
RLIMIT_NOFILE is per process. Its soft value is the enforced ceiling, while the hard value is the maximum an unprivileged process can set for itself. The limit value is one greater than the largest descriptor number the process may allocate.
Linux also accounts for file handles across the system. /proc/sys/fs/file-nr reports allocated handles and the system maximum. A single process near its own limit points to RLIMIT_NOFILE; system-wide allocation near the maximum points to broader capacity or leak pressure.
Check Linux system-wide file-handle accounting
cat /proc/sys/fs/file-nr
cat /proc/sys/fs/file-max
# file-nr fields: allocated, unused (always 0 on modern Linux), maximumFix leaks before increasing capacity
A higher limit is appropriate when measured peak concurrency legitimately requires more descriptors and the process closes resources correctly. It is not a durable fix for code that forgets to close files, response bodies, database results, pipes, or sockets on error paths.
Use application-level instrumentation where possible. Track active connections and resource acquisition versus release, reproduce under bounded load, and verify that the descriptor count returns toward baseline afterward. Restarting may restore service, but preserve enough evidence first to find the cause.
- 1Record the process ID, exact error, current descriptor count, and current soft and hard limits.
- 2Classify a sample of descriptor targets and compare multiple snapshots.
- 3Reduce overload or restart gracefully if service availability is at risk.
- 4Repair the leaking lifecycle or establish the legitimate peak requirement.
- 5Load-test the fix and alert before usage approaches the configured limit.
Apply a justified limit where the service is started
A ulimit command changes the current shell and processes subsequently launched from it. It does not retroactively change an unrelated running service. For a systemd-managed service, configure LimitNOFILE in the service unit or an override, reload the manager, and restart the service during a controlled window.
Choose a value from observed peak usage plus explicit headroom, while accounting for memory and kernel resources consumed by a much larger connection population. Before raising a soft limit above 1024, verify that the software uses poll, epoll, or another high-descriptor-capable API: programs built around select can fail once a descriptor reaches FD_SETSIZE, commonly 1024.
After restart, verify /proc/PID/limits on the actual service process instead of assuming the setting took effect.
Example systemd override
sudo systemctl edit example.service
# Add in the editor:
[Service]
LimitNOFILE=65536
sudo systemctl daemon-reload
sudo systemctl restart example.service
pid=$(systemctl show -p MainPID --value example.service)
grep -F 'Max open files' "/proc/$pid/limits"Common questions
Frequently asked questions
Does “Too many open files” refer only to regular files?
No. File descriptors can refer to regular files, directories, sockets, pipes, event objects, and other kernel resources. Network-heavy services often exhaust descriptors through sockets rather than disk files.
Why did running ulimit not change my service’s limit?
ulimit changes the calling shell and processes it starts later. An already-running service keeps its existing limits, and a supervised service normally inherits limits from systemd, a container runtime, or another process manager.
Should I simply set the file limit to unlimited?
No. Select a measured limit with headroom, verify resource costs, and fix leaks. An extremely high ceiling can delay detection while a leak consumes memory, sockets, or other system resources.
Keep learning
Sources and next steps
Related mental models
File descriptor
A file descriptor is a non-negative integer that indexes an entry in one process's descriptor table. That entry refers to a kernel-managed open resource such as a file, pipe, socket, terminal, or device.
Process and PID
A process is an operating-system execution context for a running program, including its memory, credentials, and open resources. A process ID (PID) is the number the OS uses to identify that process within a PID namespace for its current lifetime.
Filesystem hierarchy
A Unix filesystem hierarchy is a single tree of pathnames rooted at /. Mounted filesystems attach additional filesystem trees at directories within that namespace.