{"record":{"id":"69494f8f1c319737","repo":"slackhq/nebula","slug":"send-ring-corrupt","errorCode":null,"errorMessage":"Send ring corrupt","messagePattern":"Send ring corrupt","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"wintun/tun.go","lineNumber":146,"sourceCode":"\t\tpacket, err := tun.session.ReceivePacket()\n\t\tswitch err {\n\t\tcase nil:\n\t\t\tpacketSize := len(packet)\n\t\t\tcopy(buff[offset:], packet)\n\t\t\ttun.session.ReleaseReceivePacket(packet)\n\t\t\ttun.rate.update(uint64(packetSize))\n\t\t\treturn packetSize, nil\n\t\tcase windows.ERROR_NO_MORE_ITEMS:\n\t\t\tif !shouldSpin || uint64(nanotime()-start) >= spinloopDuration {\n\t\t\t\twindows.WaitForSingleObject(tun.readWait, windows.INFINITE)\n\t\t\t\tgoto retry\n\t\t\t}\n\t\t\tprocyield(1)\n\t\t\tcontinue\n\t\tcase windows.ERROR_HANDLE_EOF:\n\t\t\treturn 0, os.ErrClosed\n\t\tcase windows.ERROR_INVALID_DATA:\n\t\t\treturn 0, errors.New(\"Send ring corrupt\")\n\t\t}\n\t\treturn 0, fmt.Errorf(\"Read failed: %w\", err)\n\t}\n}\n\nfunc (tun *NativeTun) Flush() error {\n\treturn nil\n}\n\nfunc (tun *NativeTun) Write(buff []byte, offset int) (int, error) {\n\ttun.running.Add(1)\n\tdefer tun.running.Done()\n\tif atomic.LoadInt32(&tun.close) == 1 {\n\t\treturn 0, os.ErrClosed\n\t}\n\n\tpacketSize := len(buff) - offset\n\ttun.rate.update(uint64(packetSize))","sourceCodeStart":128,"sourceCodeEnd":164,"githubUrl":"https://github.com/slackhq/nebula/blob/dd8f660c0ac37903ec4080ca4d3c861ba9342ceb/wintun/tun.go#L128-L164","documentation":"NativeTun.Read reads packets from the wintun driver via a shared ring buffer. When the Windows overlapped read completes with ERROR_INVALID_DATA, the driver/signaled state indicates the send ring's internal pointers are inconsistent, and nebula returns the sentinel \"Send ring corrupt\". The TUN device's ring is unusable and traffic through it stops.","triggerScenarios":"wintun's ring-buffer offsets (head/tail) are out of bounds or mismatched — typically after driver hiccups, system sleep/resume, or memory corruption — surfacing as windows.ERROR_INVALID_DATA in Read's switch statement (wintun/tun.go:146).","commonSituations":"Windows laptops resuming from sleep while a nebula/wireguard-style TUN is active; wintun driver version mismatches after upgrades; heavy system memory pressure corrupting ring state.","solutions":["Restart the nebula process (or the network interface) to recreate the wintun session and ring buffers","Update the wintun driver (wintun.dll) to the latest version matching your nebula build","Reinstall/repair the wintun driver and reboot to clear stale driver state","Avoid sleep/resume with active tunnels or restart tunnels on resume via a wrapper script"],"exampleFix":"// before\nn, err := tun.Read(buf)\nif err != nil { l.Error(err.Error()) } // \"Send ring corrupt\" loop\n// after\nn, err := tun.Read(buf)\nif err != nil {\n    if err.Error() == \"Send ring corrupt\" {\n        l.Error(\"wintun send ring corrupt, recreating tunnel\")\n        return recreateTunnel()\n    }\n    l.Error(err.Error())\n}","handlingStrategy":"fallback","validationCode":"if err != nil && err.Error() == \"Send ring corrupt\" {\n    // recreate the tunnel/interface instead of retrying reads\n}","typeGuard":null,"tryCatchPattern":"n, err := tun.Read(buf)\nif err != nil {\n    if errors.Is(err, os.ErrClosed) { return }\n    if err.Error() == \"Send ring corrupt\" {\n        l.Error(\"wintun ring corrupt; restarting interface\")\n        if rErr := restartTunnel(); rErr != nil { l.Error(rErr.Error()) }\n        return\n    }\n    l.Error(fmt.Sprintf(\"read failed: %v\", err))\n}","preventionTips":["Keep wintun.dll and the wintun driver up to date","Restart tunnels on Windows sleep/resume events","Watch for repeated ERROR_INVALID_DATA reads as an early signal","Reboot after driver upgrades to clear stale ring state"],"tags":["nebula","wintun","windows","tun","ring-buffer"],"backgroundTag":"tun-ring-buffer-corruption","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"}