Back to Resources
October 25, 2025
5 min read

Permanent Fix for Node.js/Bun "Too Many Open Files" Error on Linux Development: The Linux Solution

Solving "Too Many Open Files" Error in Node.js/Bun on Linux: Complete Step-by-Step Instructions

J.A. Shezan
J.A. Shezan
@jashezan
Permanent Fix for Node.js/Bun "Too Many Open Files" Error on Linux Development: The Linux Solution

The sudden, intermittent crash of a development server with the cryptic "Too many open files (os error 24)" message is a frustration familiar to any modern JavaScript developer on Linux. This error halts productivity, especially when using high-performance tools like Next.js with Turbopack or Bun or Nodemon, which demand more resources than the operating system’s defaults allow.

This guide provides the definitive, copy-and-paste solution to permanently configure your Kubuntu system to eliminate this bottleneck, ensuring a stable, high-performance development environment.


1. The Development Dilemma: Why the System Fails

The Problem: File Descriptors (FDs) and Low Limits

The error is a direct violation of a core operating system limit, not a bug in your code. Every open resource—a file, a network connection, a pipe, or a monitoring process—is tracked by a File Descriptor (FD).

  • The Default: On Linux (and most Debian/Ubuntu systems), the default soft limit for FDs per process is usually 1024 or 4096.

  • The Trigger: Modern development servers, particularly those utilizing Hot Module Replacement (HMR) like Turbopack, must actively "watch" every file in your project directory, including the thousands of files nested deep within node_modules. Each watch consumes an FD, quickly exhausting the low default limit and crashing the process with os error 24.

  • The Sign: The telltale sign is the fatal message: Error [TurbopackInternalError]: Too many open files (os error 24), or similar variants like EMFILE: too many open files.

The Impact

The consequence is instability. The crash occurs occasionally because the total number of open FDs constantly fluctuates based on your workflow: the size of your project, the number of browser tabs, or other background applications (like a Language Server Protocol (LSP) running in VS Code).


2. The Solution: Three Essential System Configuration Steps

To provide stable operation, we must raise three independent, but related, system limits to a safe level (we will use a soft limit of 10000 for FDs, and 524288 for file watchers).

🚨 Prerequisite: You must use sudo for all file modifications. A simple text editor like nano is recommended.

Step 2.1: Raise the Inotify File Watcher Limit (Crucial for HMR)

This is the most critical fix for file-watching bundlers. This limit governs how many files the kernel can actively monitor.

  1. Open the kernel configuration file:

     sudo nano /etc/sysctl.conf
    
  2. Add the following line to the end of the file:

     # Increase the number of inotify file watches for development (Turbopack, webpack, etc.)
     fs.inotify.max_user_watches = 524288
    
  3. Save and exit (Ctrl+O, Enter, Ctrl+X in nano).

  4. Apply the change immediately:

     sudo sysctl -p
    

Step 2.2: Set File Descriptor Limit for PAM Sessions (limits.conf)

This change ensures that all terminal sessions (TTY, SSH, etc.) inherit a safe soft limit.

  1. Open the PAM limits configuration file:

     sudo nano /etc/security/limits.conf
    
  2. Add the following lines to the end of the file to set a soft limit of 10000 for all non-root users (*):

     # Set high soft and hard limits for max number of open file descriptors (nofile)
     # The hard limit is set high to allow future self-adjustment via ulimit -n
     * soft    nofile          10000
     * hard    nofile          65536
    
  3. Save and exit.

Step 2.3: Set File Descriptor Limit for Systemd (Linux Desktop Sessions)

Since graphical logins often bypass the limits.conf file, we must set the limit explicitly in the systemd configuration that governs user sessions.

  1. Edit the system-wide systemd configuration:

     sudo nano /etc/systemd/system.conf
    
  2. Find the [Manager] section and uncomment or add the DefaultLimitNOFILE line:

     [Manager]
     # ... other settings ...
     DefaultLimitNOFILE=10000:65536
     # ... other settings ...
    
  3. Edit the user systemd configuration:

     sudo nano /etc/systemd/user.conf
    
  4. Find the [Manager] section and uncomment or add the DefaultLimitNOFILE line:

     [Manager]
     # ... other settings ...
     DefaultLimitNOFILE=10000:65536
     # ... other settings ...
    
  5. Save and exit both files.


3. Finalize and Verify

Step 3.1: Apply All Changes

To ensure the new limits from limits.conf and the systemd configurations are correctly inherited by all new processes and sessions, a reboot is the most reliable method.

reboot

Step 3.2: Verification

After logging back in, open a new terminal and verify your new soft limit:

ulimit -n

Expected Output: The output should be 10000. If it is, your system is now configured for high-demand development.

Step 3.3: Back to Development

You can now confidently run your project without fear of the system crashing your environment:

❯ bun run dev
$ next dev

4. Troubleshooting and Reversion (The Emergency Fix)

If you needed to run your server before applying all the fixes, or if the permanent fix somehow didn't apply correctly, here is the emergency procedure.

The Temporary Command-Line Fix

You can temporarily override the soft limit for your current terminal session. This is reset when the terminal closes.

ulimit -n 8192

Run your development command in the same terminal session immediately after.

How to Revert Changes

If you encounter a new, unexpected error after making the permanent changes, you can revert the configurations to the default state:

  1. Revert Inotify: Open /etc/sysctl.conf and comment out the line you added:

     # fs.inotify.max_user_watches = 524288
    

    Then run sudo sysctl -p.

  2. Revert PAM: Open /etc/security/limits.conf and remove the two lines you added.

  3. Revert Systemd: Open /etc/systemd/system.conf and /etc/systemd/user.conf and comment out the DefaultLimitNOFILE lines:

     # DefaultLimitNOFILE=10000:65536
    

A final reboot will restore your system to its original state. However, with the limits set to 10000, you should experience robust stability without the need for reversion.

Enjoyed this article? Join the discussion on Hashnode.