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

  1. Remove tun.fd / fd-based handoff from the Windows configuration and let nebula create the wintun device itself.
  2. Use newTun (default path) by relying on tun.dev device naming instead of fds.
  3. 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

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


AI-assisted analysis of slackhq/nebula@dd8f660c0a (2026-09-03). Data as JSON: /api/errors/48c34b1b5013ea48. Report an issue: GitHub.