The Error
It usually hits when your traffic spikes: your Nginx server stops accepting connections, or a Java microservice suddenly crashes. Your logs show a blunt message: Too many open files. This happens because the process tried to open more resources than the operating system allows. Linux treats almost every I/O resource—including network sockets, database connections, and pipes—as a file. Each of these consumes a "File Descriptor" (FD).
Too many open files
Why this happens
Linux imposes safety limits to prevent a single buggy process from eating up all system memory. By default, many distributions set a limit of just 1,024 files per process. This is far too low for a modern web server or database. There are two layers to these limits:
- Soft Limit: This is the current limit enforced by the kernel. A process can increase its own soft limit up to the hard limit value.
- Hard Limit: This acts as a physical ceiling. Only a user with root privileges can increase the hard limit.
Step 1: Check Your Current Limits
Start by identifying what your system currently allows. Run these commands as the specific user running your application (e.g., www-data or mysql):
# View the soft limit
ulimit -Sn
# View the hard limit
ulimit -Hn
To see the maximum number of files the entire operating system can handle across all processes, run:
cat /proc/sys/fs/file-max
Step 2: Increase Limits for Users (Permanent)
If you run applications manually or via cron, you need to edit the /etc/security/limits.conf file. This change is permanent and survives system reboots.
sudo nano /etc/security/limits.conf
Add these lines to the bottom of the file. We recommend 65535 for most production workloads. Replace * with a specific username if you want to restrict the change:
* soft nofile 65535
* hard nofile 65535
Important: You must log out and log back in for these changes to take effect for your user session.
Step 3: Fix for Systemd Services
Standard configuration files like limits.conf often don't apply to services managed by systemd (such as Nginx, MySQL, or Node.js apps). For these, you must specify the limit in the service's own configuration.
Create an override file for your specific service:
sudo systemctl edit myservice.service
In the editor, insert the following lines:
[Service]
LimitNOFILE=65535
Save the file and exit. Now, tell systemd to reload the configuration and restart your application:
sudo systemctl daemon-reload
sudo systemctl restart myservice.service
Step 4: Increase System-wide Limits
High-concurrency servers handling millions of requests might hit the kernel's global limit. If /proc/sys/fs/file-max is low, you can increase it by editing /etc/sysctl.conf:
sudo nano /etc/sysctl.conf
Add or update the following parameter to allow 2 million open files:
fs.file-max = 2097152
Apply the new kernel settings immediately without rebooting:
sudo sysctl -p
How to Verify the Fix
Never assume a configuration change worked without checking the live process. Find the Process ID (PID) of your application and inspect its actual runtime limits:
# Find the PID (e.g., for Nginx)
pgrep nginx
# Check the limits for that specific PID
cat /proc/<PID>/limits | grep "Max open files"
The output should now reflect your new limit (e.g., 65535).
Troubleshooting Tips
Identify a File Descriptor Leak
If the error returns after a few days despite high limits, your code likely has a leak. This happens when an app opens database connections or files but forgets to close them. Use lsof to investigate what the process is holding:
# Count exactly how many files a PID has open right now
sudo lsof -p <PID> | wc -l
# See the specific files or sockets being held
sudo lsof -p <PID>
The PAM Requirement
If limits.conf changes aren't working, ensure your system is actually loading the limits module. Check /etc/pam.d/common-session and verify this line isn't commented out:
session required pam_limits.so

