slackhq/nebula · error
failed to write route.RouteMessage to socket: %w
Error message
failed to write route.RouteMessage to socket: %w
What it means
After successfully marshaling an RTM_ADD route message, addRoute() writes it to the AF_ROUTE raw socket via unix.Write. This error wraps the errno when the kernel rejects the write, meaning the route addition message was not accepted for transmission to the routing table.
Source
Thrown at overlay/tun_darwin.go:457
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 {
return fmt.Errorf("failed to write route.RouteMessage to socket: %w", err)
}
return nil
}
func delRoute(prefix netip.Prefix, gateway netroute.Addr) 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: ENOBUFS => retry after a short delay or reduce route churn; EPERM => run as root.
- Reduce the number of routes configured in tun.routes or add them more slowly if hitting kernel buffer limits.
- Verify the utun interface is still up when routes are applied (it may have been torn down concurrently).
- On macOS, consider sysctl tuning for route socket buffers if ENOBUFS recurs under heavy route churn.
Example fix
// before: applying hundreds of routes at once
routes:
- route: 10.0.0.0/8
via: 10.1.1.1
// after: aggregate to fewer, wider routes
routes:
- route: 10.0.0.0/16
via: 10.1.1.1 Defensive patterns
Strategy: retry
Try / catch
if err := iface.Activate(); err != nil {
if strings.Contains(err.Error(), "failed to write route.RouteMessage to socket") && strings.Contains(err.Error(), "no buffer space available") {
// ENOBUFS: back off and re-activate once
time.Sleep(time.Second)
return iface.Activate()
}
return err
} Prevention
- Aggregate tun.routes into fewer, wider prefixes to reduce route churn
- Run as root to avoid EPERM writes
- Add backoff between route additions when configuring many routes
- On macOS with persistent ENOBUFS, tune route socket buffer sysctls
When it happens
Trigger: Called from activate4() or addRoutes(); unix.Write on the routing socket fails, commonly with ENOBUFS (kernel route table buffer exhaustion) or EPERM (insufficient privileges).
Common situations: Adding many routes rapidly on macOS where the kernel route socket returns ENOBUFS; running unprivileged; interface state changed between socket creation and write (device gone => ENXIO).
Related errors
- unable to create AF_ROUTE socket: %v
- failed to create route.RouteMessage: %w
- failed to run tun device: %s
- failed to set tun v4 address: %s
- failed to set tun address: %s
AI-assisted analysis of slackhq/nebula@dd8f660c0a (2026-09-03).
Data as JSON: /api/errors/f3bd5280859384ae.
Report an issue: GitHub.