slackhq/nebula · error
failed to write route.RouteMessage to socket: %w
Error message
failed to write route.RouteMessage to socket: %w
What it means
addRoute successfully marshaled the RTM_ADD message but the write to the AF_ROUTE routing socket failed. This error wraps that write failure, meaning the kernel did not accept the route-add request via the routing socket.
Source
Thrown at overlay/tun_netbsd.go:498
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{
Version: unix.RTM_VERSION,
Type: unix.RTM_DELETE,
Seq: 1,
}
View on GitHub (pinned to dd8f660c0a)
Solutions
- Inspect the wrapped errno via errors.Is to distinguish EINVAL (bad message) from other I/O errors.
- Verify the target interface is up and exists at the time addRoutes runs.
- Validate prefix/gateway fields (family, validity) before building the RouteMessage.
- Retry activation if the failure was transient (e.g. EINTR) or serialize route operations to avoid races.
Defensive patterns
Strategy: retry
Validate before calling
// Ensure the interface the route points at is up before writing the route message
iface, err := net.InterfaceByName(devName)
if err != nil {
return fmt.Errorf("interface %s not present; cannot add route: %w", devName, err)
}
if iface.Flags&net.FlagUp == 0 {
return fmt.Errorf("interface %s is down", devName)
} Try / catch
var err error
for i := 0; i < 3; i++ {
if err = addRoute(prefix, gateways); err == nil {
break
}
var errno syscall.Errno
if errors.As(err, &errno) && (errno == unix.EINTR || errno == unix.EAGAIN) {
time.Sleep(time.Duration(1<<i) * 100 * time.Millisecond)
continue
}
break
}
if err != nil { return err } Prevention
- Bring the tun interface fully up before addRoutes runs.
- Serialize route operations to avoid races with concurrent route-table changes.
- Distinguish permanent kernel rejections (EINVAL) from transient errors (EINTR) via errors.As.
- Validate route fields before writing to catch message-content problems early.
When it happens
Trigger: unix.Write(sock, data) failing after a successful Marshal — e.g. the socket was closed, the kernel rejected the message (EINVAL/ESRCH), or a transient I/O error occurred on the raw socket.
Common situations: Kernel rejecting a route message with invalid fields not caught by Marshal; interface disappearing between socket creation and write; very large route batches racing with route-table changes.
Related errors
- failed to create route.RouteMessage: %w
- failed to create route.RouteMessage: %w
- failed to write route.RouteMessage to socket: %w
- failed to create route.RouteMessage: %w
- unable to create AF_ROUTE socket: %v
AI-assisted analysis of slackhq/nebula@dd8f660c0a (2026-09-03).
Data as JSON: /api/errors/a51565d866416e62.
Report an issue: GitHub.