How to Fix Next.js Broken Pipe on Ubuntu 22.04


As Senior DevOps Engineers at WebToolsWiz.com, we frequently encounter and resolve complex system-level issues impacting modern web applications. One such recurring challenge for Next.js deployments on Ubuntu 22.04 is the “Broken Pipe” error, often manifesting as EPIPE in logs or during build processes. This guide provides a professional, direct approach to diagnosing and resolving this issue.


Troubleshooting Guide: Next.js “Broken Pipe” on Ubuntu 22.04

1. The Root Cause: Why This Happens on Ubuntu 22.04

The “Broken Pipe” error (EPIPE) signifies that a process attempted to write data to a pipe, but the other end of the pipe was closed unexpectedly. In the context of Next.js on Ubuntu 22.04, this issue almost invariably points to an exhaustion of system resources, specifically the number of open file descriptors.

Next.js applications, especially during development (next dev), compilation (next build), or when serving a large number of pages, involve:

  • Reading numerous source files (JavaScript, TypeScript, CSS, images, etc.).
  • Loading a vast module tree (node_modules).
  • Spawning child processes (e.g., SWC compiler, Webpack).
  • Inter-process communication (IPC) through pipes.

Ubuntu 22.04, like most Linux distributions, imposes default limits on the number of file descriptors a single process or user can open simultaneously. If a Next.js process, or one of its child processes (e.g., the SWC or Webpack compiler process), attempts to open more file descriptors than allowed by the system’s ulimit -n setting, the operating system can terminate the offending sub-process or prevent it from creating new file descriptors. When this happens, a parent process trying to write to that now-closed pipe (or expecting a response from it) will receive an EPIPE error.

Common scenarios where this occurs:

  • Large Next.js projects with many pages or components.
  • Complex Webpack/SWC configurations.
  • Resource-constrained environments.

2. Quick Fix (CLI)

For immediate testing or temporary resolution within your current terminal session, you can increase the ulimit for the current shell.

  1. Check current limits:

    ulimit -n

    You will likely see a value like 1024 or 4096.

  2. Increase the limit (temporarily): For Next.js applications, a value like 65536 is often sufficient.

    ulimit -n 65536
  3. Verify the change:

    ulimit -n

    Confirm it now shows 65536.

  4. Run your Next.js command: Execute the command that was previously failing (e.g., npm run build, yarn build, npm run dev, yarn dev).

    Note: This change is only for the current shell session. Closing the terminal or opening a new one will revert the ulimit to its default.

3. Configuration Check (Persistent Fixes)

For a permanent solution, you need to adjust system-wide or user-specific configuration files.

A. User-Specific / System-Wide Limits (/etc/security/limits.conf)

This file defines resource limits for users and groups.

  1. Edit limits.conf:

    sudo nano /etc/security/limits.conf
  2. Add the following lines at the end of the file: These lines increase the “nofile” (number of open files) limit for all users (*) and the root user to 65536.

    # Next.js Broken Pipe Fix: Increase file descriptor limit
    *    soft nofile 65536
    *    hard nofile 65536
    root soft nofile 65536
    root hard nofile 65536
    • *: Applies to all users.
    • root: Applies specifically to the root user.
    • soft: The current enforced limit (can be increased by non-root users up to the hard limit).
    • hard: The maximum allowed limit for the specified user/group.
    • nofile: Specifies the maximum number of open file descriptors.
  3. Ensure PAM limits module is enabled: Verify that the pam_limits.so module is loaded, which is responsible for applying the limits defined in limits.conf. These files usually contain the pam_limits.so line by default on Ubuntu 22.04, but it’s worth a quick check.

    grep -q "session required pam_limits.so" /etc/pam.d/common-session || echo "session required pam_limits.so" | sudo tee -a /etc/pam.d/common-session
    grep -q "session required pam_limits.so" /etc/pam.d/common-session-noninteractive || echo "session required pam_limits.so" | sudo tee -a /etc/pam.d/common-session-noninteractive

    These commands will add the line if it’s missing, otherwise do nothing.

  4. Reboot: For these changes to take full effect across all new user sessions, a system reboot is recommended.

    sudo reboot
B. Systemd Service File (for Production Deployments)

If your Next.js application is deployed as a systemd service (e.g., using PM2, or directly running node server.js), you need to set the LimitNOFILE directive within the service unit file.

  1. Locate your service file: Typically found in /etc/systemd/system/your-nextjs-app.service.

  2. Edit the service file:

    sudo nano /etc/systemd/system/your-nextjs-app.service
  3. Add LimitNOFILE under the [Service] section:

    [Service]
    # ... other service configurations ...
    LimitNOFILE=65536
  4. Reload systemd and restart the service:

    sudo systemctl daemon-reload
    sudo systemctl restart your-nextjs-app.service

4. Verification

After applying the configuration changes, it’s crucial to verify that the new limits are in effect and that your Next.js application runs without the “Broken Pipe” error.

  1. Check User Limits (after reboot or new session): Open a new terminal session and run:

    ulimit -n

    It should now show 65536.

  2. Check Process Limits (for a running Next.js application): If your Next.js app is running as a background process or service: a. Find the Process ID (PID) of your Node.js application:

    pgrep -f "node" # Or be more specific: pgrep -f "next start"

    Let’s assume the PID is 12345. b. Check the limits for that specific process:

    cat /proc/12345/limits | grep "Max open files"

    You should see output similar to:

    Max open files            65536                65536                files
  3. Run Next.js Commands: Execute the Next.js commands that were previously failing to confirm successful completion:

    npm run build
    npm run dev
    # Or start your production service
    sudo systemctl status your-nextjs-app.service

    Monitor the terminal output or service logs (journalctl -u your-nextjs-app.service -f) for any EPIPE or “Broken Pipe” errors.

By systematically increasing the file descriptor limits, you directly address the most common cause of “Broken Pipe” errors in Next.js applications on Ubuntu 22.04, ensuring stable builds and smooth operation.