slackhq/nebula · error

could not initialize winrio

Error message

could not initialize winrio

What it means

NewRIOListener builds a Windows RIO (Registered I/O) based UDP listener. Before use it calls winrio.Initialize(); if the OS refuses to initialize the RIO extension API (unsupported platform/feature), the constructor returns "could not initialize winrio" and the fast-path listener cannot be created.

Source

Thrown at udp/udp_rio_windows.go:65

	iocp       windows.Handle
	isFull     bool
	cq         winrio.Cq
	mu         sync.Mutex
	overlapped windows.Overlapped
}

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

View on GitHub (pinned to dd8f660c0a)

Solutions

  1. Run on Windows 8/Server 2012 or newer where Registered I/O is supported
  2. Use the non-RIO UDP listener path (build/configure nebula to skip RIO, e.g. a build tag/older release using standard winsock)
  3. Update Windows/VM tooling so the RIO extension API is available to the process

Example fix

// before
u, err := udp.NewListener(l, addr, port, true, 2) // attempts RIO on windows
// after: fall back when RIO init fails
u, err := udp.NewRIOListener(l, addr, port)
if err != nil && err.Error() == "could not initialize winrio" {
    u, err = udp.NewUDPListener(l, addr, port)
}
Defensive patterns

Strategy: fallback

Validate before calling

func rioSupported() bool {
    v := windows.RtlGetVersion()
    return v.MajorVersion > 6 || (v.MajorVersion == 6 && v.MinorVersion >= 2) // Win8/2012+
}

Try / catch

u, err := udp.NewRIOListener(l, addr, port)
if err != nil {
    if err.Error() == "could not initialize winrio" {
        l.Warn("RIO unavailable, falling back to standard UDP listener")
        u, err = udp.NewUDPListener(l, addr, port)
    }
    if err != nil { return err }
}

Prevention

When it happens

Trigger: Calling udp.NewListener on Windows (which tries the RIO path via NewRIOListener) on a Windows version/edition lacking Registered I/O support, or in environments (older Windows, some containers/VMs, Wine) where winrio.Initialize returns false.

Common situations: Running nebula on Windows 7/Server 2008 R2 without the RIO-capable patch level, inside restricted containers, or under virtualization layers that do not expose RIO; also seen with incompatible winrio syscall bindings on unusual builds.

Related errors


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