slackhq/nebula · critical

bind: %w

Error message

bind: %w

What it means

NewRIOListener (Windows Registered I/O UDP path) wraps any error from RIOConn.bind — which itself creates the winrio socket, sets socket options, and binds it to the IPv6-mapped address/port. If binding fails, the whole listener is aborted with 'bind: <cause>'.

Source

Thrown at udp/udp_rio_windows.go:72

type RIOConn struct {
	isOpen  atomic.Bool
	l       *slog.Logger
	sock    windows.Handle
	rx, tx  ringBuffer
	rq      winrio.Rq
	results [packetsPerRing]winrio.Result
}

func NewRIOListener(l *slog.Logger, addr netip.Addr, port int) (*RIOConn, error) {
	if !winrio.Initialize() {
		return nil, errors.New("could not initialize winrio")
	}

	u := &RIOConn{l: l}

	err := u.bind(l, &windows.SockaddrInet6{Addr: addr.As16(), Port: port})
	if err != nil {
		return nil, fmt.Errorf("bind: %w", err)
	}

	for i := 0; i < packetsPerRing; i++ {
		err = u.insertReceiveRequest()
		if err != nil {
			return nil, fmt.Errorf("init rx ring: %w", err)
		}
	}

	u.isOpen.Store(true)
	return u, nil
}

func (u *RIOConn) bind(l *slog.Logger, sa windows.Sockaddr) error {
	var err error
	u.sock, err = winrio.Socket(windows.AF_INET6, windows.SOCK_DGRAM, windows.IPPROTO_UDP)
	if err != nil {
		return fmt.Errorf("winrio.Socket error: %w", err)

View on GitHub (pinned to dd8f660c0a)

Solutions

  1. Inspect the wrapped cause after 'bind:' (use %w unwrapping) to find the real errno (WSAEADDRINUSE, WSAEACCES, etc.)
  2. Free the UDP port or change listeners.port; verify listeners.host is a local address
  3. Run the process with required privileges or adjust Windows Firewall rules
  4. Switch the UDP implementation (config) away from RIO to the standard path if RIO setup is problematic

Example fix

// before
netstat -ano | findstr :4242  # PID 4321 holds it
taskkill /PID 4321
// after (or in config)
listeners:
  port: 4243
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-check UDP port availability on Windows
conn, err := net.ListenPacket("udp", fmt.Sprintf("%s:%d", host, port))
if err != nil { return fmt.Errorf("port %d unavailable: %w", port, err) }
conn.Close()

Try / catch

u, err := udp.NewListener(...)
if err != nil {
    if strings.Contains(err.Error(), "bind:") {
        // unwrap further (WSAEADDRINUSE etc.) and adjust port/host/privileges
    }
    return err
}

Prevention

When it happens

Trigger: Calling udp.NewListener on Windows configured for the RIO implementation when the underlying bind (or socket setup inside bind) fails — e.g. port already in use, address not local, or missing privileges.

Common situations: Another process holds the UDP port on Windows; listeners.host not assigned to the machine; firewall/antivirus blocking socket bind; RIO unavailable causing winrio.Socket failure surfaced through this wrapper.

Related errors


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