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
- 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`.
- Remove any explicit tun.dev setting (or set it to `utun`) so nebula picks the next available utun unit instead of a fixed number.
- Stop any other VPN/nebula processes that may have claimed the requested utun index.
- 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
- Leave tun.dev unset or set to `utun` so the kernel assigns a free unit
- Ensure only one nebula/VPN instance runs at a time
- Verify with `ifconfig` that the utun interface exists before/after start
- Run on the host, not inside a sandbox that blocks utun control ioctls
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
- failed to set tun v4 address: %s
- failed to set tun address: %s
- unable to determine IP version from packet
- CTLIOCGINFO: %v
- newTunFromFd not supported in Darwin
AI-assisted analysis of slackhq/nebula@dd8f660c0a (2026-09-03).
Data as JSON: /api/errors/6219f72354036859.
Report an issue: GitHub.