slackhq/nebula · error

failed to create route.RouteMessage: %w

Error message

failed to create route.RouteMessage: %w

What it means

After building a netroute.RouteMessage for the RTM_ADD request, addRoute calls route.Marshal() to serialize it into the wire format for the routing socket. A Marshal failure (e.g. invalid/nil addrs for the message type, or malformed gateway) is wrapped in this error. The library treats serialization failure as fatal for that route since the kernel request cannot even be formed.

Source

Thrown at overlay/tun_freebsd.go:644

	}

	if prefix.Addr().Is4() {
		route.Addrs = []netroute.Addr{
			unix.RTAX_DST:     &netroute.Inet4Addr{IP: prefix.Masked().Addr().As4()},
			unix.RTAX_NETMASK: &netroute.Inet4Addr{IP: prefixToMask(prefix).As4()},
			unix.RTAX_GATEWAY: gateway,
		}
	} else {
		route.Addrs = []netroute.Addr{
			unix.RTAX_DST:     &netroute.Inet6Addr{IP: prefix.Masked().Addr().As16()},
			unix.RTAX_NETMASK: &netroute.Inet6Addr{IP: prefixToMask(prefix).As16()},
			unix.RTAX_GATEWAY: gateway,
		}
	}

	data, err := route.Marshal()
	if err != nil {
		return fmt.Errorf("failed to create route.RouteMessage: %w", err)
	}

	_, err = unix.Write(sock, data[:])
	if err != nil {
		if errors.Is(err, unix.EEXIST) {
			// Try to do a change
			route.Type = unix.RTM_CHANGE
			data, err = route.Marshal()
			if err != nil {
				return fmt.Errorf("failed to create route.RouteMessage for change: %w", err)
			}
			_, err = unix.Write(sock, data[:])
			return err
		}
		return fmt.Errorf("failed to write route.RouteMessage to socket: %w", err)
	}

	return nil

View on GitHub (pinned to dd8f660c0a)

Solutions

  1. Verify the gateway netroute.Addr is non-empty and resolved before calling addRoute
  2. Log the prefix and gateway with the wrapped error to identify which route message fails to serialize
  3. Update the vendored netroute/x/sys packages if the kernel expects newer route message formats
  4. Skip-and-continue on Marshal failure in addRoutes so one bad route doesn't abort all route setup

Example fix

// before
data, err := route.Marshal()
if err != nil {
    return fmt.Errorf("failed to create route.RouteMessage: %w", err)
}
// after (guard the gateway before building the message)
if gateway.IsZero() || !prefix.IsValid() {
    return fmt.Errorf("skipping route %s: invalid gateway %v", prefix, gateway)
}
data, err := route.Marshal()
if err != nil {
    return fmt.Errorf("failed to create route.RouteMessage for %s via %v: %w", prefix, gateway, err)
}
Defensive patterns

Strategy: validation

Validate before calling

if !prefix.IsValid() {
    return fmt.Errorf("cannot add route: invalid prefix %v", prefix)
}
if gateway.IsZero() {
    return fmt.Errorf("cannot add route %v: gateway not resolved", prefix)
}

Type guard

func hasGateway(gw netroute.Addr) bool { return !gw.IsZero() }

Try / catch

if err := addRoute(prefix, gw); err != nil {
    if strings.Contains(err.Error(), "failed to create route.RouteMessage") {
        log.Warn("skipping unserializable route", "prefix", prefix, "gateway", gw, "err", err)
        return nil // skip-and-continue in addRoutes loop
    }
    return err
}

Prevention

When it happens

Trigger: route.Marshal() returns an error in addRoute — happens when the RouteMessage has an invalid Addrs bitmap/attachment, e.g. a nil or zero-value gateway netroute.Addr for the RTAX_GATEWAY slot, or incompatible RTM flags on the FreeBSD version.

Common situations: Route targets without a resolvable gateway (empty netroute.Addr); adding a default route with a gateway that failed DNS/link resolution; netroute library version incompatibility with the FreeBSD kernel's route message expectations; wrong prefix/bits producing an inconsistent Addrs map.

Related errors


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