slackhq/nebula · error
failed to create route.RouteMessage for change: %w
Error message
failed to create route.RouteMessage for change: %w
What it means
When adding a route returns EEXIST (route already present), addRoute retries by re-marshaling the same message as RTM_CHANGE. This error is returned if that second Marshal() fails, meaning the fallback route-update could not be serialized either.
Source
Thrown at overlay/tun_netbsd.go:493
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
}
func delRoute(prefix netip.Prefix, gateways []netip.Prefix) error {
sock, err := unix.Socket(unix.AF_ROUTE, unix.SOCK_RAW, unix.AF_UNSPEC)
if err != nil {
return fmt.Errorf("unable to create AF_ROUTE socket: %v", err)
}
defer unix.Close(sock)
route := netroute.RouteMessage{View on GitHub (pinned to dd8f660c0a)
Solutions
- Validate the prefix/gateway values as for the initial marshal failure (valid netip.Prefix, matching families).
- Delete the stale existing route manually (route delete) and retry to confirm the message content is the problem.
- Log the prefix, gateway, and route message fields before Marshal to pinpoint the invalid data.
- Check the netroute library version for known NetBSD RTM_CHANGE serialization issues.
Defensive patterns
Strategy: validation
Validate before calling
// Same validation as RTM_ADD applies before the RTM_CHANGE fallback
if !prefix.IsValid() || len(gateways) == 0 || !gateways[0].Addr().IsValid() {
return fmt.Errorf("cannot build RTM_CHANGE for invalid route %v", prefix)
} Try / catch
if err := addRoute(prefix, gateways); err != nil {
if strings.Contains(err.Error(), "route.RouteMessage for change") {
// EEXIST fallback also failed to marshal — remove stale route and retry once
_ = delRoute(prefix, gateways)
return addRoute(prefix, gateways)
}
return err
} Prevention
- Validate route fields before calling addRoute so both RTM_ADD and RTM_CHANGE marshal cleanly.
- Clean up stale routes from previous runs at startup to avoid the EEXIST path.
- Log the exact route being installed when change fallbacks occur.
- Prefer delete-then-add over relying on RTM_CHANGE when the route state is uncertain.
When it happens
Trigger: addRoute encountering unix.EEXIST on the initial RTM_ADD write, then route.Marshal() failing again for the RTM_CHANGE message due to malformed message fields.
Common situations: Same malformed-prefix causes as the RTM_ADD marshal failure; the route already existed from a previous run while the message fields are also subtly invalid.
Related errors
- failed to create route.RouteMessage: %w
- unable to create AF_ROUTE socket: %v
- failed to write route.RouteMessage to socket: %w
- ErrEmptyRawDetails
- ErrInvalidLocalIP
AI-assisted analysis of slackhq/nebula@dd8f660c0a (2026-09-03).
Data as JSON: /api/errors/80cd2f6933c6c0d6.
Report an issue: GitHub.