{"record":{"id":"a51565d866416e62","repo":"slackhq/nebula","slug":"failed-to-write-route-routemessage-to-socket-w-a51565","errorCode":null,"errorMessage":"failed to write route.RouteMessage to socket: %w","messagePattern":"failed to write route\\.RouteMessage to socket: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"overlay/tun_netbsd.go","lineNumber":498,"sourceCode":"\n\tdata, err := route.Marshal()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to create route.RouteMessage: %w\", err)\n\t}\n\n\t_, err = unix.Write(sock, data[:])\n\tif err != nil {\n\t\tif errors.Is(err, unix.EEXIST) {\n\t\t\t// Try to do a change\n\t\t\troute.Type = unix.RTM_CHANGE\n\t\t\tdata, err = route.Marshal()\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"failed to create route.RouteMessage for change: %w\", err)\n\t\t\t}\n\t\t\t_, err = unix.Write(sock, data[:])\n\t\t\treturn err\n\t\t}\n\t\treturn fmt.Errorf(\"failed to write route.RouteMessage to socket: %w\", err)\n\t}\n\n\treturn nil\n}\n\nfunc delRoute(prefix netip.Prefix, gateways []netip.Prefix) error {\n\tsock, err := unix.Socket(unix.AF_ROUTE, unix.SOCK_RAW, unix.AF_UNSPEC)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"unable to create AF_ROUTE socket: %v\", err)\n\t}\n\tdefer unix.Close(sock)\n\n\troute := netroute.RouteMessage{\n\t\tVersion: unix.RTM_VERSION,\n\t\tType:    unix.RTM_DELETE,\n\t\tSeq:     1,\n\t}\n","sourceCodeStart":480,"sourceCodeEnd":516,"githubUrl":"https://github.com/slackhq/nebula/blob/dd8f660c0ac37903ec4080ca4d3c861ba9342ceb/overlay/tun_netbsd.go#L480-L516","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// Ensure the interface the route points at is up before writing the route message\niface, err := net.InterfaceByName(devName)\nif err != nil {\n    return fmt.Errorf(\"interface %s not present; cannot add route: %w\", devName, err)\n}\nif iface.Flags&net.FlagUp == 0 {\n    return fmt.Errorf(\"interface %s is down\", devName)\n}","typeGuard":null,"tryCatchPattern":"var err error\nfor i := 0; i < 3; i++ {\n    if err = addRoute(prefix, gateways); err == nil {\n        break\n    }\n    var errno syscall.Errno\n    if errors.As(err, &errno) && (errno == unix.EINTR || errno == unix.EAGAIN) {\n        time.Sleep(time.Duration(1<<i) * 100 * time.Millisecond)\n        continue\n    }\n    break\n}\nif err != nil { return err }","preventionTips":["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."],"tags":["netbsd","routing","socket-write","route-message"],"backgroundTag":"route-write-failed","analyzedSha":"dd8f660c0ac37903ec4080ca4d3c861ba9342ceb","analyzedAt":"2026-09-03T11:13:55.444Z","contentChangedAt":"2026-09-03T11:13:55.444Z","schemaVersion":2},"datasetVersion":"2026-09-10T17:17:09.494Z"}