slackhq/nebula · critical
failed to set tun mtu: %w
Error message
failed to set tun mtu: %w
What it means
This error is returned by the NetBSD tun Activate method when the SIOCSIFMTU ioctl fails, i.e. the interface MTU could not be set to the configured value. Without setting the MTU, the tunnel may fragment or drop packets, so activation aborts. The error wraps the underlying errno for diagnosis.
Source
Thrown at overlay/tun_netbsd.go:318
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
}
}
return t.addRoutes(false)
}
func (t *tun) doIoctlByName(ctl uintptr, value uint32) error {
s, err := unix.Socket(unix.AF_INET, unix.SOCK_DGRAM, unix.IPPROTO_IP)
if err != nil {
return err
}
defer syscall.Close(s)View on GitHub (pinned to dd8f660c0a)
Solutions
- Check the tun.mtu config value is a sane positive number (typically 1300–1500) and remove/fix extreme values.
- Ensure the process runs as root so SIOCSIFMTU is permitted.
- Inspect the wrapped errno via errors.Is/As to distinguish EPERM from EINVAL.
- Confirm the tun device was successfully opened and configured before Activate is called.
Example fix
// before tun: mtu: 0 // after tun: mtu: 1300
Defensive patterns
Strategy: validation
Validate before calling
mtu := c.GetInt("tun.mtu", 1300)
if mtu <= 0 || mtu > 9000 {
return fmt.Errorf("invalid tun.mtu %d; use a value between 1 and 9000 (typical: 1300-1500)", mtu)
}
if os.Geteuid() != 0 {
return fmt.Errorf("setting interface MTU requires root privileges")
} Try / catch
if err := t.Activate(); err != nil {
var syscallErr syscall.Errno
if errors.As(err, &syscallErr) && syscallErr == unix.EINVAL {
// MTU value rejected — fall back to a sane default
}
return err
} Prevention
- Keep tun.mtu within the interface-supported range (typically 1300–1500 for VPNs).
- Run as root so SIOCSIFMTU is permitted.
- Do not remove or destroy the tun interface between newTun and Activate.
- Use the default MTU unless you have a specific reason to override it.
When it happens
Trigger: Calling Activate() where doIoctlByName(unix.SIOCSIFMTU, mtu) fails — typically an invalid MTU value (0, negative, or below the interface minimum), or the fd is not associated with a live interface.
Common situations: A config file with tun.mtu set to an out-of-range value; running without root; the tun interface being destroyed before activation completes.
Related errors
- failed to set tun address %s: %s
- failed to set tun device mode: %w
- failed to set tun device head: %w
- failed to set tun mtu: %w
- failed to set tun mtu: %v
AI-assisted analysis of slackhq/nebula@dd8f660c0a (2026-09-03).
Data as JSON: /api/errors/8d8a2a731c90f6e7.
Report an issue: GitHub.