slackhq/nebula · error

winrio.Socket error: %w

Error message

winrio.Socket error: %w

What it means

RIOConn.bind creates the UDP socket via winrio.Socket (Registered I/O socket, not the standard WSASocket) and wraps any failure as 'winrio.Socket error: <cause>'. Without an RIO socket no RIO listener can exist, so bind and listener creation abort.

Source

Thrown at udp/udp_rio_windows.go:90

		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)
	}

	// Enable v4 for this socket
	syscall.SetsockoptInt(syscall.Handle(u.sock), syscall.IPPROTO_IPV6, syscall.IPV6_V6ONLY, 0)

	// Disable reporting of PORT_UNREACHABLE and NET_UNREACHABLE errors from the UDP socket receive call.
	// These errors are returned on Windows during UDP receives based on the receipt of ICMP packets. Disable
	// the UDP receive error returns with these ioctl calls.
	ret := uint32(0)
	flag := uint32(0)
	size := uint32(unsafe.Sizeof(flag))
	err = syscall.WSAIoctl(syscall.Handle(u.sock), syscall.SIO_UDP_CONNRESET, (*byte)(unsafe.Pointer(&flag)), size, nil, 0, &ret, nil, 0)
	if err != nil {
		// This is a best-effort to prevent errors from being returned by the udp recv operation.
		// Quietly log a failure and continue.
		l.Debug("failed to set UDP_CONNRESET ioctl", "error", err)
	}

View on GitHub (pinned to dd8f660c0a)

Solutions

  1. Switch to the standard UDP implementation instead of RIO in the config
  2. Enable/repair IPv6 support on the host since the socket is AF_INET6
  3. Run on a Windows version with full Winsock RIO support (Windows 8/Server 2012+)
  4. Unwrap the error to read the Winsock error code (WSAEAFNOSUPPORT, WSAEPROTONOSUPPORT) and address accordingly

Example fix

// before
listeners:
  ring: rio
// after — use default udp implementation
listeners: {}
Defensive patterns

Strategy: fallback

Validate before calling

// feature-detect RIO before choosing the implementation
rioOK := runtime.GOOS == "windows" && winrioSupported() // e.g. probe winrio.Socket/close
if !rioOK { selectStandardUDPImplementation() }

Try / catch

u, err := udp.NewRIOListener(...)
if err != nil {
    var werr error
    if errors.Unwrap(err) != nil { werr = errors.Unwrap(err) }
    if strings.Contains(err.Error(), "winrio.Socket error") {
        return udp.NewListener(standardCfg) // fall back to non-RIO
    }
    return err
}

Prevention

When it happens

Trigger: Calling udp.NewRIOListener on Windows when winrio.Socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP) fails — typically because RIO is unavailable/unsupported on the platform or WSA initialization failed.

Common situations: Old or stripped-down Windows installs lacking RIO; running in environments (containers, Wine) without full Winsock RIO support; WSAStartup issues in embedded hosts; IPv6 disabled on the host so AF_INET6 socket creation fails.

Related errors


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