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, nilView on GitHub (pinned to dd8f660c0a)
Solutions
- Run on Windows 8/Server 2012 or newer where Registered I/O is supported
- Use the non-RIO UDP listener path (build/configure nebula to skip RIO, e.g. a build tag/older release using standard winsock)
- 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
- Run nebula on Windows 8/Server 2012 or newer for RIO support
- Test UDP startup on any new VM/container image before rollout
- Keep winrio syscall bindings in sync with the target Windows build
- Provide a non-RIO fallback path in deployment scripts
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
- init rx ring: %w
- winrio.Socket error: %w
- no outside connection
- ErrInvalidIPv6RemoteForSocket
- Send ring corrupt
AI-assisted analysis of slackhq/nebula@dd8f660c0a (2026-09-03).
Data as JSON: /api/errors/7480d8c85e8fdc31.
Report an issue: GitHub.