too many open files
Go Programming Language
Severity: CriticalWhat 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
-
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.
-
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.
-
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.
-
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.
-
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.