SocketException: Too many open files or maybe it’s accept4() failed: Too many open files in your nginx error log. Either way, some process just slammed into a file descriptor limit that’s been sitting there quietly since the box was provisioned. This almost always means a service is leaking sockets or file handles faster than it’s closing them, or someone left the default ulimit of 1024 in place on a server handling real traffic. Fixing the ceiling takes about two minutes. Finding out why you hit it takes a bit longer, and if you skip that part, you’ll be back here in a week with the same error at a worse time. Let’s fix both.
Key Takeaways
- Linux limits open files per user and system-wide; default soft limit is typically 1024 file descriptors.
- Check current limits instantly with ulimit -n to diagnose too many open files errors quickly.
- Temporary session fixes use ulimit -n, but permanent solutions require editing /etc/security/limits.conf or sysctl.
- Systemd services need explicit LimitNOFILE directives in unit files to override system-wide file descriptor limits.
- Monitor open file usage regularly with lsof and /proc/sys/fs/file-max to prevent resource exhaustion proactively.
Quick Fix
Check your current limit with ulimit -n. If below 4096, raise it temporarily with ulimit -n 65536, then edit /etc/security/limits.conf for permanent changes. Restart your application or session for changes to take effect.
ulimit -n && cat /proc/sys/fs/file-max && lsof | wc -l
In This Article
- When You Hit the Open Files Limit in Linux
- Check Your Current File Descriptor Limits Right Now
- Raise the Soft Limit for Your Current Session (Temporary Fix)
- Permanently Raise Per-User File Limits in /etc/security/limits.conf
- Raise System-Wide File Descriptor Limit via sysctl
- Raise File Limits for Systemd Services (systemd-specific)
- Verify the Fix Worked and Monitor for Recurrence
- Prevent “Too Many Open Files” From Happening Again
When You Hit the Open Files Limit in Linux
Every process on Linux gets a cap on how many file descriptors it can hold open at once — sockets, log files, pipes, anything with an fd number. Once a process hits that ceiling, the kernel refuses to hand out any more, and whatever tried to open the next connection or file gets an error back instead. The exact wording depends on the language runtime, but they all mean the same thing:
Too many open files— the generic form, seen in Nginx, Apache, and most C/C++ daemonsEMFILE: too many open files— Node.js and other event-loop runtimes throwing the raw errno nameulimit: open files: cannot modify limit— you tried to raise the limit interactively but hit a hard ceiling set elsewherejava.io.IOException: Too many open files— JVM apps, usually Tomcat or Kafka brokers under load
You’ll see this show up in a handful of predictable spots. A web server under a traffic spike stops accepting new connections and starts logging accept4() failed. A database — Postgres, MySQL, Redis — refuses new client connections once its own fd usage plus its connection pool exceeds the process limit. Log rotation tools choke midway through if logrotate or an app itself keeps stale file handles open after rotation instead of releasing them. And container deployments are a special case: a Docker or Kubernetes container inherits the host’s default limits unless you explicitly override them, so a service that ran fine on bare metal can hit this wall the moment it’s containerized with no ulimits block set.
Check Your Current File Descriptor Limits Right Now
Before changing anything, find out what you’re actually working with. This applies the same way on Ubuntu, Debian, RHEL, Fedora, Arch, and any other Linux distro from 2024 onward — the mechanism hasn’t changed in years.
View Your Shell’s Current Limits
ulimit -n
This shows your shell’s soft limit — the ceiling actually enforced right now. A typical default is 1024, which is low for anything running a real workload.
ulimit -Hn
This shows the hard limit — the max the soft limit can be raised to without root privileges. Expect something like 1048576 on modern distros. The soft limit is what bites you; the hard limit is just the ceiling you’re allowed to raise it to.
cat /proc/sys/fs/file-max
This is the system-wide cap across all processes combined, usually in the hundreds of thousands by default. It’s rarely the actual cause, but worth ruling out.
Find Which Process Is Exhausting File Descriptors
Guessing which service is leaking file descriptors wastes time. Check directly:
cat /proc/[pid]/limits
Replace [pid] with the process ID. Look for the Max open files row — it shows that specific process’s soft and hard limit, which can differ from your shell’s.
lsof -p [pid] | wc -l
Counts every file descriptor currently open by that process. If this number is sitting right at or near the soft limit from /proc/[pid]/limits, you’ve found your culprit.
lsof -u [username] | wc -l
Same idea, but totals across every process owned by a user — useful when a service runs multiple worker processes, like Nginx workers or a Node.js cluster. lsof ships by default on most distros; if it’s missing, install it with apt install lsof or dnf install lsof.
Raise the Soft Limit for Your Current Session (Temporary Fix)
If you just hit Too many open files and need the process working again in the next 30 seconds, this is the fix. It’s also the one that resolves the error about 70% of the time — not because it fixes the underlying cause, but because most systems ship with a soft limit of 1024, which is laughably low for anything running a database connection pool, a web server, or a log-heavy Node.js app.
ulimit -n 65536
Run this in the same shell where you’ll launch the affected process. On success it prints nothing — no output at all means it worked. If you see bash: ulimit: value exceeds hard limit, your hard limit is lower than 65536; check it with ulimit -Hn and set your target at or below that number instead.
This works identically in bash, zsh, and sh on any Linux distribution — Ubuntu, Debian, RHEL, Alpine, doesn’t matter, since ulimit is a shell builtin, not a distro-specific tool. The catch: it only affects the current shell session and any child processes you launch from it afterward. It does not touch other terminals, other users, systemd services, or anything already running. Close the terminal or reboot the box, and you’re back to the default.
Verify the Limit Changed
ulimit -n
This prints the current soft limit for open files in this shell. You should see 65536 — or whatever value you set — instead of the default 1024. If it still shows 1024, you ran the check in a different shell than the one where you set it, or the ulimit command silently failed above.
Permanently Raise Per-User File Limits in /etc/security/limits.conf
The ulimit command above resets the moment you close the shell. If you want a limit that survives reboots and applies every time a specific user or service starts, that lives in /etc/security/limits.conf. This is the fix that solves the problem for good in about 70% of cases where the running-process bump above was just a stopgap.
Edit limits.conf and Add Your Rules
sudo nano /etc/security/limits.conf
Opens the file with root privileges. Scroll past the comment block at the top — it already documents the column syntax (domain type item value) — and add your lines at the bottom:
www-data soft nofile 65536
www-data hard nofile 65536
postgres soft nofile 65536
postgres hard nofile 65536
redis soft nofile 65536
redis hard nofile 65536
Each field is separated by whitespace — a single space or tab both work, despite older docs insisting on tabs. If you want every user on the box to inherit the new ceiling, use a wildcard instead of naming each account:
* soft nofile 65536
* hard nofile 65536
This works on any distro using PAM for login sessions — RHEL 8/9, Debian 12, Ubuntu 22.04/24.04, and Alpine with linux-pam installed. Confirm PAM is wired up by checking that /etc/pam.d/common-session (Debian/Ubuntu) or /etc/pam.d/system-auth (RHEL) includes a line for pam_limits.so — it’s there by default on all mainstream installs, so you rarely need to touch it.
Restart the Service or Log Out and Back In
limits.conf only applies to new login sessions and freshly spawned processes — it doesn’t touch anything already running. For a system service:
sudo systemctl restart postgresql
Swap in nginx, redis-server, or whatever daemon you edited above. For interactive shells, just log out and back in, then confirm the new context took effect:
id
ulimit -n
id confirms which user you’re running as, and ulimit -n should now report 65536 without you having to set it manually. One catch worth flagging: systemd-managed services often ignore limits.conf entirely and need their own LimitNOFILE= directive in the unit file — covered in the next section.
Raise System-Wide File Descriptor Limit via sysctl
Per-user limits control how many files one account can open. But there’s a separate ceiling for the entire kernel — the total file descriptors every process on the box can hold combined. If you’re running a busy Elasticsearch cluster, a high-connection-count proxy, or a database with hundreds of client connections, you can hit this ceiling even after fixing limits.conf. The symptom looks identical: Too many open files in your logs, but ulimit -n for the affected user shows plenty of headroom.
Add the sysctl Rule and Apply It
Don’t edit /etc/sysctl.conf directly — it gets overwritten or fought over during package upgrades on some distros. Drop your setting into /etc/sysctl.d/ instead, which is modular and survives upgrades cleanly:
echo 'fs.file-max = 2097152' | sudo tee -a /etc/sysctl.d/99-custom.conf
This appends the rule to a dedicated config file. Apply it immediately:
sudo sysctl -p /etc/sysctl.d/99-custom.conf
Expected output:
fs.file-max = 2097152
No reboot required — sysctl applies kernel parameters live. Use 2097152 for high-load systems (large Kafka brokers, busy reverse proxies), and 1048576 for standard application servers. This works identically across RHEL 8/9, Debian 12, Ubuntu 22.04/24.04, and Alpine — fs.file-max is a core kernel parameter, not a distro-specific feature.
Verify the System-Wide Limit
Confirm the kernel picked up the new value directly from the proc filesystem:
cat /proc/sys/fs/file-max
Expected output:
2097152
This number is the hard ceiling for the entire machine — no process, no matter what its ulimit -n says, can push total open files past it. If this value looks correct but you’re still hitting errors, the bottleneck is back at the per-user or per-process level, not the kernel.
Raise File Limits for Systemd Services (systemd-specific)
If the process throwing Too many open files is managed by systemd — nginx, PostgreSQL, Docker, a custom Node.js unit — none of the limits.conf or sysctl changes above apply to it. Systemd services get their file descriptor limits from the unit file, full stop. This is the fix that actually matters on RHEL 8/9, Debian 11/12, Ubuntu 20.04 through 24.04, and any containerized deployment running under systemd.
Create or Edit the Service Override
Don’t edit the vendor’s unit file directly — package upgrades will overwrite it. Use the built-in override mechanism instead:
sudo systemctl edit nginx
This opens an editor (usually vim or nano, whatever $EDITOR is set to) with a blank drop-in template. Add these lines inside the marked section:
[Service]
LimitNOFILE=65536
Save and exit. systemctl edit writes this automatically to /etc/systemd/system/nginx.service.d/override.conf — you don’t need to create the directory yourself. Swap nginx for whatever unit is failing: postgresql, docker, or a custom myapp.service. For high-connection workloads (a busy reverse proxy or a WebSocket server holding thousands of idle connections), bump this to 262144.
Reload and Restart the Service
Systemd needs to re-read unit configuration before the new limit takes effect:
sudo systemctl daemon-reload && sudo systemctl restart nginx
No output means success. Confirm the service is actually running with the new limit applied:
systemctl status nginx
Look for active (running) in green. To double-check the limit itself took hold, grab the PID from that output and run cat /proc/ — the Max open files row should read 65536 in both the soft and hard columns.
Verify the Fix Worked and Monitor for Recurrence
Applying a limit and confirming a process actually sees it are two different things. Don’t trust the config file — check the live process.
Check Limits Applied to a Running Process
Find the PID of the process you just restarted:
ps aux | grep nginx
Pick the master process PID (not a worker), then check what the kernel is actually enforcing for it:
cat /proc/12345/limits | grep 'open files'
Expected output looks like this:
Max open files 65536 65536 files
Those two numbers are soft and hard limits. If either still shows 1024 or 4096, your override didn’t take effect — go back and confirm systemctl daemon-reload actually ran and the service was fully restarted, not reloaded.
Monitor Open File Count Over Time
A one-time check doesn’t catch a slow leak. Watch the count live:
watch -n 5 'lsof -p 12345 | wc -l'
This refreshes every 5 seconds and shows the current file descriptor count for that PID. A healthy process holds a roughly stable number under steady load. If the count climbs steadily and never drops — even during idle periods — you’ve got a file descriptor leak in the application itself, and no ulimit value will fix that. Check for unclosed sockets, log handles, or database connections in the app code.
For a longer-running check, tail the system log for recurrence:
tail -f /var/log/syslog | grep 'Too many open files'
Silence here over a few hours under real traffic is your confirmation the fix held.
Prevent “Too Many Open Files” From Happening Again
Fixing the limit once doesn’t mean you’re done. Bake the right values into your deployment so nobody has to rediscover this at 2am.
- Set limits at deployment time. Put your
LimitNOFILE=overrides in the same Ansible playbook, Terraform module, or Dockerfile that provisions the box — not as a manual step someone forgets on the next server. - Container limits. Docker defaults to 1048576 for
nofileon most modern hosts, but always set it explicitly with--ulimit nofile=65536:65536in yourdocker runor Compose file rather than trusting the daemon default. - Monitor file descriptor usage in production. Export
process_open_fdsfrom node_exporter into Prometheus and graph it in Grafana against theprocess_max_fdsceiling. On AWS, a CloudWatch custom metric doing the samelsof -p $PID | wc -lcheck on a cron works fine if you’re not running Prometheus. - Review code for leaks. Unclosed file handles, sockets left open after exceptions, and missing
finallyblocks are the actual root cause more often than the limit itself. - Use connection pooling (PgBouncer, HikariCP) instead of opening a new database socket per request.
- Rotate logs with
logrotateso no single log file, or pile of forgotten ones, eats through your descriptor budget.
Applies uniformly across distros and deployment models — bare metal, VMs, containers. Pair LimitNOFILE with MemoryLimit and CPUQuota in your systemd unit for full resource containment, not just file handles.
Frequently Asked Questions
What is the default maximum number of open files in Linux?
The default soft limit is typically 1024 file descriptors per user, while the hard limit is often 65536. System-wide limits are controlled by /proc/sys/fs/file-max, which defaults to a calculated value based on available RAM.
How do I check how many files are currently open on my Linux system?
Use ulimit -n to see your current limit, lsof to list all open files, or cat /proc/sys/fs/file-max for the system-wide maximum. Check per-process open files with lsof -p PID or cat /proc/PID/limits.
How do I permanently increase the open files limit in Linux?
Edit /etc/security/limits.conf to set per-user limits, or modify /etc/sysctl.conf to raise fs.file-max system-wide. For systemd services, add LimitNOFILE=65536 to the service unit file, then reload with systemctl daemon-reload.
Why am I getting too many open files error even after raising the limit?
Verify changes took effect with ulimit -n and restart your application or shell session. Check if systemd service limits override your settings, or if the hard limit is lower than your soft limit request.
Related Reads
- Unable to Locate Package apt Fix: Linux Troubleshooting
Fix ‘unable to locate package’ apt errors on Linux. Copy-paste commands to update repos, fix sources, and resolve missin…
- How to Solve Unable to Locate Package Error on Linux
Fix ‘unable to locate package’ errors on Ubuntu, Debian, CentOS. Copy-paste commands to refresh repos, check spelling, a…
- How to Reset SSH Connection: 5-Minute Fixes
SSH connection frozen or hanging? Copy-paste fixes ordered by likelihood. Covers hung sessions, timeout errors, and stal…