slackhq/nebula · error

generate GUID failed: %w

Error message

generate GUID failed: %w

What it means

newTun derives a stable wintun adapter GUID from the device name via generateGUIDByDeviceName(deviceName). If that fails, the error is wrapped as 'generate GUID failed'. The GUID generation is hash-based on tun.dev, so failure usually means an invalid or unusable device name.

Source

Thrown at overlay/tun_windows.go:67

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,
		networkCategory: cat,
		setCategory:     setCat,
		bypassWDF:       c.GetBool("tun.windows_bypass_wdf", true),
		l:               l,
	}

View on GitHub (pinned to dd8f660c0a)

Solutions

  1. Set tun.dev to a simple ASCII alphanumeric name (e.g. 'nebula') in the config.
  2. Remove control characters, spaces, or non-ASCII characters from tun.dev.
  3. Keep the device name within Windows adapter-name length limits.
  4. If you didn't set tun.dev, verify the config file parses as expected (c.GetString fallback producing an empty value) and fix the config key/format.

Example fix

// before
tun:
  dev: "Nebula VPN (corp)"
// after
tun:
  dev: "Nebula"
Defensive patterns

Strategy: validation

Validate before calling

name := c.GetString("tun.dev", "nebula")
valid := regexp.MustCompile(`^[A-Za-z0-9_-]{1,32}$`)
if !valid.MatchString(name) {
	return fmt.Errorf("tun.dev %q must be 1-32 ASCII letters, digits, _ or -", name)
}

Try / catch

tun, err := overlay.NewTun(cfg, logger, prefixes, false)
if err != nil && strings.Contains(err.Error(), "generate GUID failed") {
	// fix tun.dev and retry startup; non-transient config error
}

Prevention

When it happens

Trigger: generateGUIDByDeviceName returns an error for the name from c.GetString("tun.dev", "") — e.g. a device name with characters wintun rejects, an empty name combined with a hashing constraint, or an internal conversion failure.

Common situations: tun.dev set to a name with illegal characters or excessive length for a Windows adapter; misconfigured or templated configs that produce empty/odd device names; non-ASCII device names.

Related errors


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