{"record":{"id":"5648f99cac158312","repo":"slackhq/nebula","slug":"failed-to-write-route-routemessage-to-socket-w-5648f9","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_openbsd.go","lineNumber":477,"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":459,"sourceCodeEnd":495,"githubUrl":"https://github.com/slackhq/nebula/blob/dd8f660c0ac37903ec4080ca4d3c861ba9342ceb/overlay/tun_openbsd.go#L459-L495","documentation":"addRoute built and marshaled a RouteMessage successfully, but the write to the AF_ROUTE raw socket failed (and the failure was not EEXIST). The error is wrapped as 'failed to write route.RouteMessage to socket'. This means the kernel routing socket refused the route addition.","triggerScenarios":"unix.Write(sock, data) on the AF_ROUTE socket returns a non-EEXIST error during addRoute (called from addIp or addRoutes) — e.g. EPERM for missing privileges, EINVAL/ESRCH for a bad route, or ENOBUFS under kernel pressure.","commonSituations":"Running nebula without root/CAP_NET_ADMIN on OpenBSD so the routing socket rejects RTM_ADD; a gateway that doesn't exist in the routing table (ESRCH); route conflicts with another daemon (routing daemons like ospfd/relayd).","solutions":["Run the process as root or with the required privileges — OpenBSD routing sockets need effective privileges.","Check that the gateway address is itself reachable via another route; RTM_ADD with an unreachable gateway fails.","Retry or ignore EEXIST-like races; if another tool manages overlapping routes, remove the conflicting tun.routes entries.","Capture the wrapped errno (%w) from the error chain to distinguish EPERM vs ESRCH vs EINVAL and fix accordingly."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// check privileges early\nif unix.Geteuid() != 0 {\n\treturn errors.New(\"route management requires root privileges on OpenBSD\")\n}","typeGuard":null,"tryCatchPattern":"if err := addRoute(prefix, gws); err != nil {\n\tvar syscallErr unix.Errno\n\tif errors.As(err, &syscallErr) {\n\t\tswitch syscallErr {\n\t\tcase unix.EPERM: /* rerun as root */\n\t\tcase unix.EEXIST: /* already present */\n\t\tdefault: log.Error(\"route add failed\", \"errno\", syscallErr)\n\t\t}\n\t}\n}","preventionTips":["Run nebula as root (or with routing privileges) on OpenBSD.","Ensure gateways referenced by routes exist in the routing table.","Avoid running conflicting routing daemons over the same prefixes."],"tags":["openbsd","routing","route-socket","permissions"],"backgroundTag":"route-socket-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"}