Ad Space — Top Banner

too many open files

Go Programming Language

Severity: Critical

What Does This Error Mean?

Your program has opened more files (or network connections) than the OS allows. Every file, socket, and network connection uses a file descriptor. This usually means you are opening files or connections without closing them.

Affected Models

  • Go 1.21
  • Go 1.22
  • Go 1.23
  • Go 1.24

Common Causes

  • Opening files in a loop without closing them (missing file.Close())
  • HTTP client or server connections not being closed after use
  • Database connections accumulating without being returned to the pool
  • Goroutine leaks that hold open file handles or sockets
  • The OS file descriptor limit (ulimit) is set too low for the workload

How to Fix It

  1. Find where you open files and add defer file.Close() immediately after opening.

    f, err := os.Open(name); if err != nil { return err }; defer f.Close() — this pattern prevents leaks.

  2. For HTTP clients, ensure response bodies are closed: defer resp.Body.Close()

    Not closing response bodies is one of the most common causes of this error in Go web code.

  3. Check your database connection pool settings — set a sensible max open connections.

    db.SetMaxOpenConns(25) limits the pool. Without this, the pool can grow unboundedly.

  4. Check the current file descriptor limit on Linux or macOS with: ulimit -n

    The default is often 1024. For high-traffic servers, raise it to 65536 or higher in /etc/security/limits.conf.

  5. Use lsof -p PID | wc -l to count open file descriptors for your process.

    Watch this number over time. If it keeps growing without stabilizing, you have a leak.

When to Call a Professional

If this error appears in production under normal load, escalate to your ops or infrastructure team. Increasing ulimit is a system-level change that should be done deliberately. A code audit for resource leaks is also strongly recommended.

Frequently Asked Questions

Why does Go count network connections as file descriptors?

On Unix-based systems, everything is a file — including sockets. Each open TCP connection uses one file descriptor. A busy HTTP server can hit the limit quickly if connections are not closed.

Does defer file.Close() work inside a loop?

No — defer runs when the function returns, not when the loop iteration ends. Inside a loop, close files explicitly: file.Close() at the end of each iteration. Or refactor the loop body into a separate function and use defer there.

How do I raise the file descriptor limit on Linux?

Run ulimit -n 65536 in your shell for a temporary change. For permanent changes, edit /etc/security/limits.conf. For systemd services, add LimitNOFILE=65536 to the service unit file.