{"record":{"id":"48c34b1b5013ea48","repo":"slackhq/nebula","slug":"newtunfromfd-not-supported-in-windows","errorCode":null,"errorMessage":"newTunFromFd not supported in Windows","messagePattern":"newTunFromFd not supported in Windows","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"overlay/tun_windows.go","lineNumber":55,"sourceCode":"\tMTU             int\n\tRoutes          atomic.Pointer[[]Route]\n\trouteTree       atomic.Pointer[bart.Table[routing.Gateways]]\n\tguid            windows.GUID\n\tnetworkCategory networkCategory\n\tsetCategory     bool\n\tbypassWDF       bool\n\twdfBypass       closer\n\tl               *slog.Logger\n\n\ttun *wintun.NativeTun\n}\n\nfunc (t *winTun) Read(b []byte) (int, error) {\n\treturn t.tun.Read(b, 0)\n}\n\nfunc newTunFromFd(_ *config.C, _ *slog.Logger, _ int, _ []netip.Prefix) (Device, error) {\n\treturn nil, fmt.Errorf(\"newTunFromFd not supported in Windows\")\n}\n\nfunc newTun(c *config.C, l *slog.Logger, vpnNetworks []netip.Prefix, _ bool) (*winTun, error) {\n\terr := checkWinTunExists()\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"can not load the wintun driver: %w\", err)\n\t}\n\n\tdeviceName := c.GetString(\"tun.dev\", \"\")\n\tguid, err := generateGUIDByDeviceName(deviceName)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"generate GUID failed: %w\", err)\n\t}\n\n\tcat, setCat, err := parseNetworkCategory(c.GetString(\"tun.network_category\", \"private\"))\n\tif err != nil {\n\t\treturn nil, err\n\t}","sourceCodeStart":37,"sourceCodeEnd":73,"githubUrl":"https://github.com/slackhq/nebula/blob/dd8f660c0ac37903ec4080ca4d3c861ba9342ceb/overlay/tun_windows.go#L37-L73","documentation":"On Windows, newTunFromFd is intentionally unimplemented; wintun devices cannot be adopted from a pre-existing file descriptor. Calling it always returns 'newTunFromFd not supported in Windows'. Use newTun, which creates the wintun device from config instead.","triggerScenarios":"Any code path that calls newTunFromFd on a Windows build — typically a config that sets tun.fd, or service handoff logic assuming fd-based tunnel adoption works on Windows.","commonSituations":"Porting Linux configs (tun.pre_opened fd from systemd socket activation) to Windows; running nebula under a supervisor that passes fds; writing cross-platform launchers.","solutions":["Remove tun.fd / fd-based handoff from the Windows configuration and let nebula create the wintun device itself.","Use newTun (default path) by relying on tun.dev device naming instead of fds.","If fd adoption is required, run on a Unix platform or contribute wintun fd adoption upstream."],"exampleFix":"// before\nc:\n  tun:\n    fd: 3\n// after\nc:\n  tun:\n    dev: Nebula   # wintun device created by nebula itself","handlingStrategy":"validation","validationCode":"if runtime.GOOS == \"windows\" {\n\tif fd, ok := c.GetInt(\"tun.fd\"); ok && fd > 0 {\n\t\treturn errors.New(\"tun.fd is not supported on Windows; let nebula create the wintun device\")\n\t}\n}","typeGuard":null,"tryCatchPattern":"dev, err := overlay.NewTunFromFd(cfg, logger, fd, prefixes)\nif err != nil && strings.Contains(err.Error(), \"Windows\") {\n\t// platform unsupported: switch to NewTun or fail fast with a clear message\n}","preventionTips":["Keep Windows configs free of tun.fd / fd handoff settings.","Use tun.dev naming instead of pre-opened descriptors on Windows.","Guard cross-platform launch code with runtime.GOOS checks."],"tags":["windows","tun","wintun","unsupported-feature"],"backgroundTag":"unsupported-operation","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"}