valyala/fasthttp · error
cannot determine backlog to pass to listen(2): %w
Error message
cannot determine backlog to pass to listen(2): %w
What it means
tcplisten wraps the raw listen(2) syscall to create reusable, deferred-accept TCP listeners. When cfg.Backlog is not set (<=0), fdSetup reads the kernel's somaxconn value to derive a backlog; if that lookup fails, it cannot call listen(2) and returns this error wrapping the cause. It surfaces from NewListener.
Source
Thrown at tcplisten/tcplisten.go:129
if err = enableDeferAccept(fd); err != nil {
return err
}
}
if cfg.FastOpen {
if err = enableFastOpen(fd); err != nil {
return err
}
}
if err = unix.Bind(fd, sa); err != nil {
return fmt.Errorf("cannot bind to %q: %w", addr, err)
}
backlog := cfg.Backlog
if backlog <= 0 {
if backlog, err = soMaxConn(); err != nil {
return fmt.Errorf("cannot determine backlog to pass to listen(2): %w", err)
}
}
if err = unix.Listen(fd, backlog); err != nil {
return fmt.Errorf("cannot listen on %q: %w", addr, err)
}
return nil
}
func getSockaddr(network, addr string) (sa unix.Sockaddr, soType int, err error) {
tcpAddr, err := net.ResolveTCPAddr(network, addr)
if err != nil {
return nil, -1, err
}
switch network {
case "tcp4":
var sa4 unix.SockaddrInet4View on GitHub (pinned to c96f600972)
Solutions
- Set an explicit Backlog (>0) in the tcplisten.Config so soMaxConn() is never called
- Check /proc/sys/net/core/somaxconn is readable by the process user (cat it manually)
- Relax container/seccomp or AppArmor restrictions on /proc/sys reads
- Check the wrapped %w error for the underlying read failure
Example fix
// before
cfg := tcplisten.Config{ReusePort: true} // Backlog unset -> procfs lookup
ln, err := tcplisten.NewListener(cfg, "tcp", ":8080")
// after
cfg := tcplisten.Config{ReusePort: true, Backlog: 1024} // explicit backlog skips somaxconn lookup
ln, err := tcplisten.NewListener(cfg, "tcp", ":8080") Defensive patterns
Strategy: validation
Validate before calling
func backlogConfigured(cfg tcplisten.Config) bool { return cfg.Backlog > 0 }
if !backlogConfigured(cfg) {
if b, err := ioutil.ReadFile("/proc/sys/net/core/somaxconn"); err != nil && !os.IsNotExist(err) {
cfg.Backlog = 1024 // avoid procfs-dependent lookup
}
} Try / catch
ln, err := tcplisten.NewListener(cfg, network, addr)
if err != nil {
var sysErr *fs.PathError
if errors.As(err, &sysErr) || strings.Contains(err.Error(), "somaxconn") {
cfg.Backlog = 1024
ln, err = tcplisten.NewListener(cfg, network, addr)
}
} Prevention
- Always set an explicit Backlog in production configs
- Smoke-test listeners in the same container/seccomp profile as production
- Never assume /proc/sys is readable in hardened environments
When it happens
Trigger: Calling tcplisten.NewListener with a Config whose Backlog is 0 or negative on Linux when soMaxConn() fails — i.e. /proc/sys/net/core/somaxconn exists but cannot be read due to permissions/other I/O error (a missing file is tolerated and falls back to unix.SOMAXCONN).
Common situations: Hardened containers/seccomp profiles blocking reads from /proc; pseudo-filesystems where /proc/sys is read-restricted or returns other I/O errors; unusual environments (some CI sandboxes) where the procfs file is present but unreadable.
Related errors
- cannot listen on %q: %w
- fasthttp: dialing to the given tcp address timed out
- couldn't find dns entries for the given domain: try using du
- only tcp, tcp4, or tcp6 is supported
- value is negative, cannot convert to uintptr
AI-assisted analysis of valyala/fasthttp@c96f600972 (2026-08-31).
Data as JSON: /api/errors/4a1c42232daa1e63.
Report an issue: GitHub.