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