slackhq/nebula · error

failed to set tun device mode: %w

Error message

failed to set tun device mode: %w

What it means

Activate() puts the tun device into IFF_BROADCAST mode via the TUNSIFMODE ioctl. If that ioctl fails, this error wraps the errno, meaning the kernel refused to set the device mode (device in wrong state, bad descriptor, or permission issue).

Source

Thrown at overlay/tun_netbsd.go:307

		if err != nil {
			return err
		}
		defer syscall.Close(s)

		if err := ioctl(uintptr(s), SIOCAIFADDR_IN6, uintptr(unsafe.Pointer(&req))); err != nil {
			return fmt.Errorf("failed to set tun address %s: %s", cidr.Addr().String(), err)
		}
		return nil
	}

	return fmt.Errorf("unknown address type %v", cidr)
}

func (t *tun) Activate() error {
	mode := int32(unix.IFF_BROADCAST)
	err := ioctl(uintptr(t.fd), TUNSIFMODE, uintptr(unsafe.Pointer(&mode)))
	if err != nil {
		return fmt.Errorf("failed to set tun device mode: %w", err)
	}

	v := 1
	err = ioctl(uintptr(t.fd), TUNSIFHEAD, uintptr(unsafe.Pointer(&v)))
	if err != nil {
		return fmt.Errorf("failed to set tun device head: %w", err)
	}

	err = t.doIoctlByName(unix.SIOCSIFMTU, uint32(t.MTU))
	if err != nil {
		return fmt.Errorf("failed to set tun mtu: %w", err)
	}

	for i := range t.vpnNetworks {
		err = t.addIp(t.vpnNetworks[i])
		if err != nil {
			return err
		}

View on GitHub (pinned to dd8f660c0a)

Solutions

  1. Ensure Activate() is called once, right after newTun() and before Close()
  2. Verify the tun device still exists and the fd is valid (recreate with ifconfig tunN create if destroyed)
  3. Run with root privileges as TUNSIFMODE requires device access

Example fix

// before
tun.Close()
tun.Activate() // fd already closed
// after
tun.Activate()
// ... use tun ...
tun.Close()
Defensive patterns

Strategy: try-catch

Validate before calling

// call Activate exactly once, immediately after newTun
var activateOnce sync.Once
func safeActivate(t *tun) error {
    var err error
    activateOnce.Do(func() { err = t.Activate() })
    return err
}

Try / catch

if err := tun.Activate(); err != nil {
    log.Printf("tun activate failed: %v — device may need recreation (ifconfig tunN create)", err)
}

Prevention

When it happens

Trigger: ioctl(fd, TUNSIFMODE, IFF_BROADCAST) fails because t.fd is invalid/closed, the device was already configured to an incompatible mode, or the caller lacks privileges.

Common situations: Calling Activate after the device was destroyed; double activation racing with Close; unprivileged execution.

Related errors


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