{"record":{"id":"938f25ef0a5896a6","repo":"slackhq/nebula","slug":"error-tx-open-w","errorCode":null,"errorMessage":"error tx.Open(): %w","messagePattern":"error tx\\.Open\\(\\): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"udp/udp_rio_windows.go","lineNumber":127,"sourceCode":"\tret = 0\n\tflag = 0\n\tsize = uint32(unsafe.Sizeof(flag))\n\tSIO_UDP_NETRESET := uint32(syscall.IOC_IN | syscall.IOC_VENDOR | 15)\n\terr = syscall.WSAIoctl(syscall.Handle(u.sock), SIO_UDP_NETRESET, (*byte)(unsafe.Pointer(&flag)), size, nil, 0, &ret, nil, 0)\n\tif err != nil {\n\t\t// This is a best-effort to prevent errors from being returned by the udp recv operation.\n\t\t// Quietly log a failure and continue.\n\t\tl.Debug(\"failed to set UDP_NETRESET ioctl\", \"error\", err)\n\t}\n\n\terr = u.rx.Open()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error rx.Open(): %w\", err)\n\t}\n\n\terr = u.tx.Open()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error tx.Open(): %w\", err)\n\t}\n\n\tu.rq, err = winrio.CreateRequestQueue(u.sock, packetsPerRing, 1, packetsPerRing, 1, u.rx.cq, u.tx.cq, 0)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error CreateRequestQueue: %w\", err)\n\t}\n\n\terr = windows.Bind(u.sock, sa)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error windows.Bind(): %w\", err)\n\t}\n\n\treturn nil\n}\n\nfunc (u *RIOConn) ListenOut(r EncReader, flush func()) error {\n\tbuffer := make([]byte, MTU)\n","sourceCodeStart":109,"sourceCodeEnd":145,"githubUrl":"https://github.com/slackhq/nebula/blob/dd8f660c0ac37903ec4080ca4d3c861ba9342ceb/udp/udp_rio_windows.go#L109-L145","documentation":"This error wraps failure of the transmit (tx) ring buffer's Open() during RIO UDP listener setup on Windows, after rx.Open() has succeeded. The tx side allocates its own completion queue and send buffers via winrio. bind() aborts and propagates the underlying OS error via %w.","triggerScenarios":"NewRIOListener -> bind() where u.tx.Open() fails: winrio.CreateCompletionQueue for the tx side returns an OS error (resource limits, invalid parameters, RIO unavailable).","commonSituations":"Same environments as rx.Open failures - non-paged pool exhaustion, per-process RIO completion queue limits reached, antivirus/kernel network filter drivers rejecting RIO registration.","solutions":["Inspect the wrapped OS error for the precise winrio failure code.","Lower packetsPerRing to shrink the tx completion queue and registered buffer footprint.","Close other RIO sockets or reboot to reclaim non-paged pool if WSAENOBUFS-style errors appear.","Verify Windows version and winsock support for Registered I/O."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"if runtime.GOOS != \"windows\" { return errors.New(\"RIO listener only exists on windows\") }\n// ensure system has headroom before opening large rings\nif packetsPerRing > 1024 { return fmt.Errorf(\"packetsPerRing %d too large\", packetsPerRing) }","typeGuard":"func isTxOpenErr(err error) bool { return err != nil && strings.Contains(err.Error(), \"tx.Open()\") }","tryCatchPattern":"conn, err := udp.NewListener(logger, settings)\nif err != nil && strings.Contains(err.Error(), \"tx.Open()\") {\n\t// retry once with smaller rings or fail over to a non-RIO path\n}","preventionTips":["Avoid oversized tx ring sizes; match them to expected send throughput.","Free RIO resources deterministically (Close sockets) when tearing down.","Watch for kernel network filter drivers (AV) that can break RIO registration.","Log the unwrapped OS error code for postmortems."],"tags":["windows","udp","rio","network"],"backgroundTag":"udp-bind-failed","analyzedSha":"dd8f660c0ac37903ec4080ca4d3c861ba9342ceb","analyzedAt":"2026-09-03T11:13:55.444Z","contentChangedAt":"2026-09-03T11:13:55.444Z","schemaVersion":2},"datasetVersion":"2026-09-10T17:17:09.494Z"}