slackhq/nebula · error

failed to set mtu %v on the default route %v; %v

Error message

failed to set mtu %v on the default route %v; %v

What it means

Raised by tun.setDefaultRoute (called from reload and Activate) when applying the configured DefaultMTU to the detected default route fails. The message includes the MTU, the default route (dr), and the underlying error, so you can see exactly which route couldn't be modified.

Source

Thrown at overlay/tun_linux.go:565

	err := netlink.RouteReplace(&nr)
	if err != nil {
		t.l.Warn("Failed to set default route MTU, retrying", "error", err, "cidr", cidr)
		//retry twice more -- on some systems there appears to be a race condition where if we set routes too soon, netlink says `invalid argument`
		for i := 0; i < 2; i++ {
			time.Sleep(100 * time.Millisecond)
			err = netlink.RouteReplace(&nr)
			if err == nil {
				break
			} else {
				t.l.Warn("Failed to set default route MTU, retrying",
					"error", err,
					"cidr", cidr,
					"mtu", t.DefaultMTU,
				)
			}
		}
		if err != nil {
			return fmt.Errorf("failed to set mtu %v on the default route %v; %v", t.DefaultMTU, dr, err)
		}
	}

	return nil
}

func (t *tun) addRoutes(logErrors bool) error {
	// Path routes
	routes := *t.Routes.Load()
	for _, r := range routes {
		if !r.Install {
			continue
		}

		dr := &net.IPNet{
			IP:   r.Cidr.Masked().Addr().AsSlice(),
			Mask: net.CIDRMask(r.Cidr.Bits(), r.Cidr.Addr().BitLen()),
		}

View on GitHub (pinned to dd8f660c0a)

Solutions

  1. Read dr and err in the message: if the route is 'none'/missing, ensure the host has a default route for that family.
  2. Run with CAP_NET_ADMIN to allow route attribute changes.
  3. Check that DefaultMTU in config is a valid MTU (e.g. 1300-1400 for overhead-heavy tunnels).
  4. If the default route flaps (DHCP), retry reload after the network stabilizes.
  5. Disable/adjust default-route MTU handling via config if your overlay doesn't need it.

Example fix

// before
# ip route  (no default route for the family)
// after — provide a default route or set an explicit MTU
# ip route add default via 10.0.0.1
tun: { default_mtu: 1300 }
Defensive patterns

Strategy: retry

Validate before calling

func defaultRouteExists(fam int) bool {
    routes, err := netlink.RouteList(nil, fam)
    if err != nil { return false }
    for _, r := range routes {
        if r.Dst == nil { return true } // default route
    }
    return false
}

Try / catch

if err := activateOverlay(); err != nil {
    if strings.Contains(err.Error(), "failed to set mtu") && strings.Contains(err.Error(), "default route") {
        time.Sleep(time.Second)
        err = activateOverlay() // default route may have just flapped
    }
}

Prevention

When it happens

Trigger: reload() or Activate() runs while the host's default route cannot have its MTU updated via netlink — route not found (wrong address family), permission denied, or the route changed concurrently.

Common situations: No IPv4/IPv6 default route on the host while the CIDR requires one; lack of CAP_NET_ADMIN; flapping default route (DHCP renewals, VPN-over-VPN) changing the route between lookup and update.

Related errors


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