slackhq/nebula · error

init rx ring: %w

Error message

init rx ring: %w

What it means

After binding, NewRIOListener posts packetsPerBallast... specifically packetsPerRing receive requests into the RIO receive ring via insertReceiveRequest; if any post fails the listener is aborted with 'init rx ring: <cause>'. This means the RIO completion/recv ring could not be initialized.

Source

Thrown at udp/udp_rio_windows.go:78

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

	// 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.

View on GitHub (pinned to dd8f660c0a)

Solutions

  1. Check the wrapped cause after 'init rx ring:' for the specific winio/winrio error
  2. Switch the UDP implementation to the standard (non-RIO) Windows path
  3. Reboot/update Windows and NIC drivers if RIO resources appear exhausted
  4. Reduce packetsPerRing / ring sizing if memory registration limits are the cause

Example fix

// before (config forcing RIO)
udp:
  implementation: rio
// after
udp:
  implementation: standard
Defensive patterns

Strategy: fallback

Validate before calling

// only select RIO when the platform is known to support it
useRIO := runtime.GOOS == "windows" && windowsRIOAvailable()

Try / catch

u, err := udp.NewListener(rioCfg)
if err != nil && strings.Contains(err.Error(), "init rx ring") {
    log.Warn("RIO rx ring init failed; falling back to standard UDP", "err", err)
    u, err = udp.NewListener(stdCfg)
}

Prevention

When it happens

Trigger: Calling udp.NewRIOListener (via udp.NewListener on Windows RIO) when winrio.RIOReceive/queue registration fails while filling the receive ring — e.g. RIO buffer/queue exhaustion, invalid memory registration, or RIO disabled by the OS.

Common situations: Windows versions where RIO misbehaves; resource limits on registered memory; antivirus/NDIS filter drivers interfering with RIO; misconfigured ring sizing in the udp package options.

Related errors


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