slackhq/nebula · error

failed to get tun flags: %s

Error message

failed to get tun flags: %s

What it means

Right after setting the MTU, Activate reads the interface flags with the SIOCGIFFLAGS ioctl to learn the device state before configuring routes/addresses. If that ioctl fails, the errno is wrapped in this error. It usually indicates the interface does not exist or the caller lacks privilege to query it.

Source

Thrown at overlay/tun_darwin.go:188

		unix.IPPROTO_IP,
	)
	if err != nil {
		return err
	}
	defer unix.Close(s)

	fd := uintptr(s)

	// Set the MTU on the device
	ifm := ifreqMTU{Name: devName, MTU: int32(t.DefaultMTU)}
	if err = ioctl(fd, unix.SIOCSIFMTU, uintptr(unsafe.Pointer(&ifm))); err != nil {
		return fmt.Errorf("failed to set tun mtu: %v", err)
	}

	// Get the device flags
	ifrf := ifReq{Name: devName}
	if err = ioctl(fd, unix.SIOCGIFFLAGS, uintptr(unsafe.Pointer(&ifrf))); err != nil {
		return fmt.Errorf("failed to get tun flags: %s", err)
	}

	linkAddr, err := getLinkAddr(t.Device)
	if err != nil {
		return err
	}
	if linkAddr == nil {
		return fmt.Errorf("unable to discover link_addr for tun interface")
	}
	t.linkAddr = linkAddr

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

View on GitHub (pinned to dd8f660c0a)

Solutions

  1. Confirm the interface exists: `ifconfig <devName>`; fix tun.dev if it does not.
  2. Run with root privileges so interface ioctls are allowed.
  3. Ensure no other VPN tool is deleting/recreating the utun while nebula activates; stop competing VPNs.
  4. Restart nebula so a fresh utun is created and activated atomically.

Example fix

// before (nebula.yml)
tun:
  dev: utun99   # never created / wrong name
// after
tun:
  dev: utun50   # or omit dev so nebula uses the name it just created
Defensive patterns

Strategy: validation

Validate before calling

out, err := exec.Command("ifconfig", devName).Output()
if err != nil || len(out) == 0 {
    return fmt.Errorf("interface %s does not exist before activate", devName)
}

Try / catch

if err := start(); err != nil && strings.Contains(err.Error(), "failed to get tun flags") {
    // interface missing or permission denied: check ifconfig and privileges
}

Prevention

When it happens

Trigger: ioctl(fd, SIOCGIFFLAGS, ifReq{devName}) fails during tun.Activate — devName not present in the interface table, fd not a valid control socket for that device, or permission denial.

Common situations: tun.dev configured with a name that was never created; interface destroyed between connect and activate (competing VPN); running without sufficient privileges in restricted macOS environments.

Related errors


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