slackhq/nebula · error
newTunFromFd not supported in Windows
Error message
newTunFromFd not supported in Windows
What it means
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.
Source
Thrown at overlay/tun_windows.go:55
MTU int
Routes atomic.Pointer[[]Route]
routeTree atomic.Pointer[bart.Table[routing.Gateways]]
guid windows.GUID
networkCategory networkCategory
setCategory bool
bypassWDF bool
wdfBypass closer
l *slog.Logger
tun *wintun.NativeTun
}
func (t *winTun) Read(b []byte) (int, error) {
return t.tun.Read(b, 0)
}
func newTunFromFd(_ *config.C, _ *slog.Logger, _ int, _ []netip.Prefix) (Device, error) {
return nil, fmt.Errorf("newTunFromFd not supported in Windows")
}
func newTun(c *config.C, l *slog.Logger, vpnNetworks []netip.Prefix, _ bool) (*winTun, error) {
err := checkWinTunExists()
if err != nil {
return nil, fmt.Errorf("can not load the wintun driver: %w", err)
}
deviceName := c.GetString("tun.dev", "")
guid, err := generateGUIDByDeviceName(deviceName)
if err != nil {
return nil, fmt.Errorf("generate GUID failed: %w", err)
}
cat, setCat, err := parseNetworkCategory(c.GetString("tun.network_category", "private"))
if err != nil {
return nil, err
}View on GitHub (pinned to dd8f660c0a)
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.
Example fix
// before
c:
tun:
fd: 3
// after
c:
tun:
dev: Nebula # wintun device created by nebula itself Defensive patterns
Strategy: validation
Validate before calling
if runtime.GOOS == "windows" {
if fd, ok := c.GetInt("tun.fd"); ok && fd > 0 {
return errors.New("tun.fd is not supported on Windows; let nebula create the wintun device")
}
} Try / catch
dev, err := overlay.NewTunFromFd(cfg, logger, fd, prefixes)
if err != nil && strings.Contains(err.Error(), "Windows") {
// platform unsupported: switch to NewTun or fail fast with a clear message
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- Send ring corrupt
- can not load the wintun driver: %w
- generate GUID failed: %w
- create TUN device failed: %w
- unknown tun.network_category %q (expected public, private, d
AI-assisted analysis of slackhq/nebula@dd8f660c0a (2026-09-03).
Data as JSON: /api/errors/48c34b1b5013ea48.
Report an issue: GitHub.