slackhq/nebula · error

unable to set SO_REUSEPORT: %w

Error message

unable to set SO_REUSEPORT: %w

What it means

NewListener sets SO_REUSEPORT so multiple nebula processes/threads can bind the same UDP port, and wraps the setsockopt(2) errno if the kernel rejects it. The fd is closed and listener creation aborts. The wrapped value is the raw errno from unix.SetsockoptInt.

Source

Thrown at udp/udp_linux.go:54

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()
		sa = sa6
	}
	if err = unix.Bind(fd, sa); err != nil {
		_ = unix.Close(fd)
		return nil, fmt.Errorf("unable to bind to socket: %w", err)
	}

View on GitHub (pinned to dd8f660c0a)

Solutions

  1. Check the wrapped errno to identify the exact failure and confirm the kernel supports SO_REUSEPORT (Linux >= 3.9)
  2. Disable the multi-listener option so Multi=false and SO_REUSEPORT is not requested
  3. Update to a newer kernel or run on a platform with full setsockopt support
  4. Audit seccomp/AppArmor profiles to allow setsockopt on SOL_SOCKET

Example fix

// before
listeners:
  batch: 64
  multi: true
// after
listeners:
  batch: 64
  multi: false
Defensive patterns

Strategy: try-catch

Validate before calling

// feature check before enabling multi
if runtime.GOOS == "linux" {
    var kv kernel.Version // from uname
    if kv.LessThan(3, 9, 0) { disableMulti() }
}

Try / catch

l, err := udp.NewListener(...)
if err != nil {
    var soErr *fmt.Error // wrapped setsockopt errno
    if strings.Contains(err.Error(), "SO_REUSEPORT") {
        // fall back to single-listener config and retry
    }
    return err
}

Prevention

When it happens

Trigger: Calling udp.NewListener with Multi=true (or config enabling multiple UDP listeners) when setsockopt(SO_REUSEPORT) fails on the fresh fd.

Common situations: Kernels or OS builds without SO_REUSEPORT support; seccomp filters blocking setsockopt; running under an OS emulation layer (e.g. old WSL1) that does not implement the option.

Related errors


AI-assisted analysis of slackhq/nebula@dd8f660c0a (2026-09-03). Data as JSON: /api/errors/007c19ef5932292d. Report an issue: GitHub.