slackhq/nebula · error

failed to run tun device: %s

Error message

failed to run tun device: %s

What it means

During Activate(), after the utun interface has been created and given an address, nebula sets the interface flags via the SIOCSIFFLAGS ioctl to mark it IFF_UP and IFF_RUNNING. This error wraps the raw errno when that ioctl fails, meaning the kernel refused to bring the utun device up. It indicates the interface name in the ioctl request no longer matches a live kernel network interface.

Source

Thrown at overlay/tun_darwin.go:217

	for _, network := range t.vpnNetworks {
		if network.Addr().Is4() {
			err = t.activate4(network)
			if err != nil {
				return err
			}
		} else {
			err = t.activate6(network)
			if err != nil {
				return err
			}
		}
	}

	// Run the interface
	ifrf.Flags = ifrf.Flags | unix.IFF_UP | unix.IFF_RUNNING
	if err = ioctl(fd, unix.SIOCSIFFLAGS, uintptr(unsafe.Pointer(&ifrf))); err != nil {
		return fmt.Errorf("failed to run tun device: %s", err)
	}

	// Unsafe path routes
	return t.addRoutes(false)
}

func (t *tun) activate4(network netip.Prefix) error {
	s, err := unix.Socket(
		unix.AF_INET,
		unix.SOCK_DGRAM,
		unix.IPPROTO_IP,
	)
	if err != nil {
		return err
	}
	defer unix.Close(s)

	ifr := ifreqAlias4{

View on GitHub (pinned to dd8f660c0a)

Solutions

  1. Check the error's underlying errno via the %s suffix (e.g. ENXIO/ENODEV means the device is gone) and confirm the utun interface still exists with `ifconfig`.
  2. Remove any explicit tun.dev setting (or set it to `utun`) so nebula picks the next available utun unit instead of a fixed number.
  3. Stop any other VPN/nebula processes that may have claimed the requested utun index.
  4. Ensure nebula is not running inside a container/sandbox that blocks utun kernel control requests; run it on the host or grant the needed entitlements.

Example fix

// before (fixed unit, may collide)
tun:
  dev: utun7
// after (let the kernel pick a free unit)
tun:
  dev: utun
Defensive patterns

Strategy: try-catch

Try / catch

err := iface.Activate()
if err != nil {
    if strings.Contains(err.Error(), "failed to run tun device") {
        // retry with auto-selected utun unit (tun.dev: utun) after checking `ifconfig`
    }
    return err
}

Prevention

When it happens

Trigger: Activate() is called at tun setup; the SIOCSIFFLAGS ioctl on the AF_INET UDP control socket fails (e.g. the utun unit number requested in tun.dev was taken so the actual device differs, or the interface disappeared between SIOCGIFFLAGS and SIOCSIFFLAGS).

Common situations: Running on a macOS/Darwin host where another nebula instance or VPN client already claimed the requested utunN unit; sandboxed/containerized environments where utun devices are not permitted; stale device names after the previous process exited without closing the tun.

Related errors


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