slackhq/nebula · critical
unable to open socket: %w
Error message
unable to open socket: %w
What it means
NewListener wraps the raw errno from unix.Socket(AF_INET/AF_INET6, SOCK_DGRAM, IPPROTO_UDP) when the kernel refuses to create a UDP socket. The library throws it because without a raw fd it cannot build its StdConn UDP listener at all. The wrapped err is the syscall errno (e.g. EMFILE, ENFILE, EAFNOSUPPORT, EPROTONOSUPPORT).
Source
Thrown at udp/udp_linux.go:48
// udp_linux_writebatch.go.
bw *batchWriter
groSupported bool
}
func NewListener(l *slog.Logger, s Settings) (Conn, error) {
af := unix.AF_INET6
if s.Listen.Addr().Is4() {
af = unix.AF_INET
}
syscall.ForkLock.RLock()
fd, err := unix.Socket(af, unix.SOCK_DGRAM, unix.IPPROTO_UDP)
if err == nil {
unix.CloseOnExec(fd)
}
syscall.ForkLock.RUnlock()
if err != nil {
return nil, fmt.Errorf("unable to open socket: %w", err)
}
if s.Multi {
if err = unix.SetsockoptInt(fd, unix.SOL_SOCKET, unix.SO_REUSEPORT, 1); err != nil {
_ = unix.Close(fd)
return nil, fmt.Errorf("unable to set SO_REUSEPORT: %w", err)
}
}
var sa unix.Sockaddr
port := int(s.Listen.Port())
if s.Listen.Addr().Is4() {
sa4 := &unix.SockaddrInet4{Port: port}
sa4.Addr = s.Listen.Addr().As4()
sa = sa4
} else {
sa6 := &unix.SockaddrInet6{Port: port}
sa6.Addr = s.Listen.Addr().As16()View on GitHub (pinned to dd8f660c0a)
Solutions
- Raise the process/file-descriptor limit (ulimit -n, systemd LimitNOFILE, container rlimit) and restart
- Check the wrapped errno in the error chain (errors.Unwrap / %w) to identify the exact syscall failure
- Verify the container/runtime seccomp profile permits socket(AF_INET*, SOCK_DGRAM)
- Confirm the kernel supports the requested address family (IPv4 vs IPv6) and UDP protocol
Example fix
// before (shell) ulimit -n # 256, too low // after (systemd unit) [Service] LimitNOFILE=65535
Defensive patterns
Strategy: try-catch
Validate before calling
// pre-flight: ensure fd headroom before starting nebula
n, err := syscall.Getrlimit(syscall.RLIMIT_NOFILE)
if err == nil && n.Cur < 1024 {
return fmt.Errorf("RLIMIT_NOFILE too low (%d); raise it before starting", n.Cur)
} Try / catch
l, err := udp.NewListener(...)
if err != nil {
var errno syscall.Errno
if errors.As(err, &errno) && (errors.Is(errno, syscall.EMFILE) || errors.Is(errno, syscall.ENFILE)) {
// raise RLIMIT_NOFILE / retry after freeing fds
}
return fmt.Errorf("udp listener: %w", err)
} Prevention
- Set LimitNOFILE/ulimit -n generously (e.g. 65535) for nebula units and containers
- Check wrapped errno with errors.As(err, &syscall.Errno) to pinpoint the syscall failure
- Avoid fd leaks elsewhere in the process; monitor /proc/<pid>/fd count
- Test startup in a container with the production seccomp profile
When it happens
Trigger: Calling udp.NewListener (directly or via nebula's interface setup) when the process is out of file descriptors (EMFILE/ENFILE), the address family is unavailable, or UDP sockets are blocked by the kernel/container seccomp profile.
Common situations: Containers with a low ulimit -n; Kubernetes pods hitting the node-wide file-descriptor cap; hardened seccomp/AppArmor policies blocking socket(2); kernels built without UDP/IPv6 support.
Related errors
- unable to set SO_REUSEPORT: %w
- unable to bind to socket: %w
- unsupported sock type: %T
- WriteBatch: len(bufs)=%d != len(addrs)=%d
- sendmmsg made no progress
AI-assisted analysis of slackhq/nebula@dd8f660c0a (2026-09-03).
Data as JSON: /api/errors/147a75cc226d3e37.
Report an issue: GitHub.