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 (RTM_ADD), addRoute marshals it to wire format before writing it to the routing socket. This error is returned when route.Marshal() fails, meaning the route message could not be serialized — usually because required fields (addresses, prefixes) are malformed.

Source

Thrown at overlay/tun_netbsd.go:483

			unix.RTAX_DST:     &netroute.Inet4Addr{IP: prefix.Masked().Addr().As4()},
			unix.RTAX_NETMASK: &netroute.Inet4Addr{IP: prefixToMask(prefix).As4()},
			unix.RTAX_GATEWAY: &netroute.Inet4Addr{IP: gw.Addr().As4()},
		}
	} else {
		gw, err := selectGateway(prefix, gateways)
		if err != nil {
			return err
		}
		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: &netroute.Inet6Addr{IP: gw.Addr().As16()},
		}
	}

	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. Validate configured vpnNetworks and gateway prefixes parse to valid netip.Prefix values (netip.ParsePrefix) before adding routes.
  2. Ensure the gateway address family matches the prefix family and that Addr().IsValid() is true.
  3. Log the prefix and gateway values when this error occurs to identify the malformed input.
  4. Update the netroute dependency if a Marshal bug for a specific address family is suspected.
Defensive patterns

Strategy: validation

Validate before calling

func validateRoute(prefix netip.Prefix, gateways []netip.Prefix) error {
    if !prefix.IsValid() {
        return fmt.Errorf("invalid route prefix")
    }
    for _, gw := range gateways {
        if !gw.IsValid() || !gw.Addr().IsValid() {
            return fmt.Errorf("invalid gateway %v", gw)
        }
        if gw.Addr().Is4() != prefix.Addr().Is4() {
            return fmt.Errorf("gateway family %v does not match prefix family %v", gw, prefix)
        }
    }
    return nil
}

Try / catch

if err := addRoute(prefix, gateways); err != nil {
    if strings.Contains(err.Error(), "failed to create route.RouteMessage") {
        return fmt.Errorf("malformed route data (prefix=%v gateways=%v): %w", prefix, gateways, err)
    }
    return err
}

Prevention

When it happens

Trigger: addRoute (via addRoutes) receiving a prefix or gateway whose binary form cannot be marshaled, e.g. an IPv6 gateway misformatted for the address-family slot or a zero-length address.

Common situations: A VPN network configured with an invalid CIDR; a gateway address of the wrong family (IPv4 vs IPv6) for the route being added; corrupted netip.Prefix values from config parsing.

Related errors


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