slackhq/nebula · critical
can not load the wintun driver: %w
Error message
can not load the wintun driver: %w
What it means
newTun on Windows requires the wintun.dll driver. checkWinTunExists() tries to load wintun.dll; when that fails, nebula wraps the cause as 'can not load the wintun driver'. Without wintun.dll the TUN device cannot be created and nebula cannot start.
Source
Thrown at overlay/tun_windows.go:61
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
}
t := &winTun{
Device: deviceName,
vpnNetworks: vpnNetworks,
MTU: c.GetInt("tun.mtu", DefaultMTU),
guid: *guid,View on GitHub (pinned to dd8f660c0a)
Solutions
- Download the official wintun distribution and place the architecture-correct wintun.dll next to nebula.exe (or in PATH).
- Verify DLL architecture matches the nebula binary (x64/x86/arm64).
- Check antivirus/EDR quarantine logs and whitelist wintun.dll.
- Ensure the wintun.dll version is one supported by your nebula release and not corrupted (re-download and compare checksums).
Example fix
// before nebula.exe in C:\nebula\ with no wintun.dll anywhere on PATH // after C:\nebula\ nebula.exe wintun.dll (amd64 build matching the nebula binary)
Defensive patterns
Strategy: validation
Validate before calling
if _, err := os.Stat(filepath.Join(exeDir, "wintun.dll")); err != nil {
return errors.New("wintun.dll missing next to nebula.exe; install the official wintun distribution")
} Try / catch
tun, err := overlay.NewTun(cfg, logger, prefixes, false)
if err != nil && strings.Contains(err.Error(), "wintun driver") {
// surface install guidance: correct-arch wintun.dll beside the binary
return fmt.Errorf("install wintun: %w", err)
} Prevention
- Bundle the architecture-matching wintun.dll with every nebula deployment.
- Verify checksums of wintun.dll after download.
- Whitelist the DLL in antivirus/EDR policies.
- Confirm DLL arch matches binary arch (x64/x86/arm64).
When it happens
Trigger: newTun calls checkWinTunExists() and LoadLibrary/finds no wintun.dll on the search path, an architecture-mismatched DLL (e.g. 32-bit DLL with 64-bit nebula), or a corrupted/incompatible wintun version.
Common situations: wintun.dll missing next to nebula.exe or in PATH; wrong architecture (x86 vs x64 vs arm64) DLL; antivirus quarantining wintun.dll; running from a stripped-down environment where the DLL wasn't bundled.
Related errors
- Send ring corrupt
- newTunFromFd not supported in Windows
- 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/0ad4a5c6b722218f.
Report an issue: GitHub.