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
- Check the wrapped cause after 'init rx ring:' for the specific winio/winrio error
- Switch the UDP implementation to the standard (non-RIO) Windows path
- Reboot/update Windows and NIC drivers if RIO resources appear exhausted
- 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
- Keep Windows and NIC drivers updated where RIO is used
- Provide a standard-implementation fallback in deployment config
- Avoid NDIS filter/AV drivers known to break RIO in production images
- Size ring buffers within registered-memory limits
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.