Back to blog

How to Fix the Too Many Open Files Error in Linux and Node.js

If you deploy high-traffic applications, database nodes, or real-time WebSocket servers on Linux, you will likely encounter this runtime crash: "Error: EMFILE, too many open files".

This error means your application has hit the operating system's limit for concurrent open files, preventing it from opening new configuration files, logging outputs, or accepting new network sockets.

In this guide, we will analyze what file descriptors are, show you how to inspect your system limits using ulimit and lsof, and walk through persistent system configurations to resolve this error.

Everything is a File in Linux

To understand why this error happens, you must look at Linux's core architecture: everything is a file.

In Linux, a File Descriptor (FD) is a unique index pointer generated by the kernel to track open resources. It is not limited to plain text files. The kernel consumes a file descriptor for:

  • Regular files on your SSD.
  • Active HTTP/HTTPS network connections.
  • Open database connections.
  • TCP/UDP socket connections.
  • System pipes and log streams.

If your web server is handling 2,000 concurrent WebSocket connections, it is occupying at least 2,000 file descriptors.

Step 1: Check Your Current Limits

Linux limits the number of file descriptors a single user or process can open to prevent buggy scripts from consuming all kernel resources.

Checking User Limits (ulimit)

To check the file descriptor limits for your current shell user, run:

# Check the soft limit (the limit a process can exceed dynamically)
ulimit -Sn

# Check the hard limit (the absolute maximum ceiling allowed by the kernel)
ulimit -Hn

On a default Ubuntu or Debian server setup, the soft limit is typically set to 1024. This means if your Node.js application attempts to handle more than 1,024 concurrent client requests, it crashes with the EMFILE error.

Checking System-Wide Limits

To check the maximum file descriptors the entire system kernel can manage collectively, inspect this virtual file:

cat /proc/sys/fs/file-max

This limit is usually high (e.g., several millions), so you rarely hit system-wide limits. The bottleneck is almost always the user or process limit.

Step 2: Identify File Descriptor Leaks

If your application triggers EMFILE but you have very few users, you likely have a resource leak in your code (such as files opened using fs.open that are never closed, or database connections left dangling).

To trace how many file descriptors a running process is consuming, find the process ID (PID) and run:

# Get the total count of open file descriptors for a specific PID
ls -l /proc/YOUR_PID/fd/ | wc -l

# List the specific files, sockets, and pipes the process is holding open
lsof -p YOUR_PID

If you see thousands of open connections to the same database port or unclosed temporary files, you must fix the resource lifecycle in your code.

Step 3: Increase the File Limits persistently

If your traffic is legitimate and your code is leak-free, you must increase the operating system limits.

Option A: Edit limits.conf (System-wide for Users)

Open the PAM configuration file:

sudo nano /etc/security/limits.conf

Add these lines at the bottom of the file (replacing root or admin with the username running your application, or use * for all users):

*    soft    nofile    65536
*    hard    nofile    65536

This increases the file descriptor limit to 65,536. Save the file and restart your user session (log out and log back in) for the changes to apply.

Option B: Configure Systemd Service Limits

If you manage your Node.js app using a systemd service file (e.g., /etc/systemd/system/node-app.service), the settings in limits.conf are ignored. You must declare the limits directly inside the service definition file.

Open your service file and add LimitNOFILE inside the [Service] block:

[Unit]
Description=My Node.js Application

[Service]
ExecStart=/usr/bin/node /app/dist/server.js
Restart=always
User=www-data
# Set the maximum open file descriptor limit for this process
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target

Reload the systemd manager and restart your service:

sudo systemctl daemon-reload
sudo systemctl restart node-app.service

Conclusion

The "Too Many Open Files" crash is caused by operating system protections limiting file descriptor allocations. By checking current limits using ulimit -n, isolating leaks using lsof -p, configuring /etc/security/limits.conf for system users, and defining LimitNOFILE inside systemd service files, you can scale your network and database connections safely.