{"record":{"id":"96ca915e33829445","repo":"slackhq/nebula","slug":"unable-to-bind-to-socket-w","errorCode":null,"errorMessage":"unable to bind to socket: %w","messagePattern":"unable to bind to socket: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"udp/udp_linux.go","lineNumber":71,"sourceCode":"\t\t\t_ = unix.Close(fd)\n\t\t\treturn nil, fmt.Errorf(\"unable to set SO_REUSEPORT: %w\", err)\n\t\t}\n\t}\n\n\tvar sa unix.Sockaddr\n\tport := int(s.Listen.Port())\n\tif s.Listen.Addr().Is4() {\n\t\tsa4 := &unix.SockaddrInet4{Port: port}\n\t\tsa4.Addr = s.Listen.Addr().As4()\n\t\tsa = sa4\n\t} else {\n\t\tsa6 := &unix.SockaddrInet6{Port: port}\n\t\tsa6.Addr = s.Listen.Addr().As16()\n\t\tsa = sa6\n\t}\n\tif err = unix.Bind(fd, sa); err != nil {\n\t\t_ = unix.Close(fd)\n\t\treturn nil, fmt.Errorf(\"unable to bind to socket: %w\", err)\n\t}\n\n\tout := &StdConn{sysFd: fd, isV4: s.Listen.Addr().Is4(), l: l, batch: s.Batch}\n\n\tout.bw = newBatchWriter(fd, out.isV4, l, s.Offloads)\n\n\t// GRO coalesces same-flow datagrams into superpackets that must be split back apart via the delivered gso_size cmsg\n\t// batch == 1 means the caller wants plain single-datagram reads with MTU-sized buffers, so leave it off.\n\tif s.Batch > 1 && s.Offloads {\n\t\tout.prepareGRO()\n\t}\n\n\treturn out, nil\n}\n\n// udpGROBufferSize sizes the per-entry recvmmsg buffer when UDP_GRO is on.\n// The kernel stitches a run of same-flow datagrams into a single skb whose\n// length is bounded by sk_gso_max_size (65535)","sourceCodeStart":53,"sourceCodeEnd":89,"githubUrl":"https://github.com/slackhq/nebula/blob/dd8f660c0ac37903ec4080ca4d3c861ba9342ceb/udp/udp_linux.go#L53-L89","documentation":"NewListener wraps the errno from unix.Bind when the kernel refuses to bind the UDP socket to the configured listen address/port. The fd is closed and listener creation fails. The wrapped err is the raw bind errno (EADDRINUSE, EACCES, EADDRNOTAVAIL).","triggerScenarios":"Calling udp.NewListener with listeners.host/port that is already bound by another process without SO_REUSEPORT, an address not assigned to the host, or a privileged port (<1024) without CAP_NET_BIND_SERVICE/root.","commonSituations":"Another instance of nebula (or any UDP service) already holds the port; listen host typo (address not on this machine); binding port 443/UDP as non-root in a container without capabilities; stale nebula process after a crash.","solutions":["Free the port: stop the conflicting process (ss -ulnp | grep <port>) or change listeners.port in config","Verify listeners.host is an address actually assigned to the machine (or use 0.0.0.0)","Run with CAP_NET_BIND_SERVICE or a non-privileged port if binding <1024","Check the wrapped errno in the error chain to distinguish EADDRINUSE vs EACCES vs EADDRNOTAVAIL"],"exampleFix":"// before (nebula.yaml, non-root)\nlisteners:\n  host: 0.0.0.0\n  port: 443\n// after\nlisteners:\n  host: 0.0.0.0\n  port: 4242","handlingStrategy":"validation","validationCode":"// before starting: verify the port is free and the address exists\nfunc portFree(host string, port int) error {\n    conn, err := net.ListenUDP(\"udp\", &net.UDPAddr{IP: net.ParseIP(host), Port: port})\n    if err != nil { return err }\n    conn.Close()\n    return nil\n}","typeGuard":null,"tryCatchPattern":"l, err := udp.NewListener(...)\nif err != nil {\n    var errno syscall.Errno\n    if errors.As(err, &errno) {\n        switch errno {\n        case syscall.EADDRINUSE: // stop conflicting process or change port\n        case syscall.EACCES:    // need root/CAP_NET_BIND_SERVICE\n        case syscall.EADDRNOTAVAIL: // fix listeners.host\n        }\n    }\n    return err\n}","preventionTips":["Validate listeners.host is a local interface address before launch","Pick non-privileged ports (>1024) for non-root deployments","Use systemd socket activation or grant CAP_NET_BIND_SERVICE for low ports","Check ss -ulnp / netstat for port conflicts in deployment automation"],"tags":["udp","linux","bind","address-in-use","privileged-port"],"backgroundTag":"address-already-in-use","analyzedSha":"dd8f660c0ac37903ec4080ca4d3c861ba9342ceb","analyzedAt":"2026-09-03T11:13:55.444Z","contentChangedAt":"2026-09-03T11:13:55.444Z","schemaVersion":2},"datasetVersion":"2026-09-10T17:17:09.494Z"}