{"record":{"id":"ca9f21bb66e42301","repo":"slackhq/nebula","slug":"sys-connect-v","errorCode":null,"errorMessage":"SYS_CONNECT: %v","messagePattern":"SYS_CONNECT: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"overlay/tun_darwin.go","lineNumber":110,"sourceCode":"\tfd, err := unix.Socket(unix.AF_SYSTEM, unix.SOCK_DGRAM, unix.AF_SYS_CONTROL)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"system socket: %v\", err)\n\t}\n\n\tvar ctlInfo = &unix.CtlInfo{}\n\tcopy(ctlInfo.Name[:], utunControlName)\n\n\terr = unix.IoctlCtlInfo(fd, ctlInfo)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"CTLIOCGINFO: %v\", err)\n\t}\n\n\terr = unix.Connect(fd, &unix.SockaddrCtl{\n\t\tID:   ctlInfo.Id,\n\t\tUnit: uint32(ifIndex) + 1,\n\t})\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"SYS_CONNECT: %v\", err)\n\t}\n\n\tname, err = unix.GetsockoptString(fd, unix.AF_SYS_CONTROL, _UTUN_OPT_IFNAME)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to retrieve tun name: %w\", err)\n\t}\n\n\terr = unix.SetNonblock(fd, true)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"SetNonblock: %v\", err)\n\t}\n\n\tt := &tun{\n\t\tf:           os.NewFile(uintptr(fd), \"\"),\n\t\tDevice:      name,\n\t\tvpnNetworks: vpnNetworks,\n\t\tDefaultMTU:  c.GetInt(\"tun.mtu\", DefaultMTU),\n\t\tl:           l,","sourceCodeStart":92,"sourceCodeEnd":128,"githubUrl":"https://github.com/slackhq/nebula/blob/dd8f660c0ac37903ec4080ca4d3c861ba9342ceb/overlay/tun_darwin.go#L92-L128","documentation":"newTun connects the control socket to the utun kernel control using SockaddrCtl with the resolved control ID and a unit number derived from the requested interface index (Unit = ifIndex + 1). If unix.Connect fails, this error wraps the errno. Commonly this means the requested utun unit number is already taken or invalid.","triggerScenarios":"Explicitly configuring a tun device name (e.g. utun5) whose unit number is already in use, requesting a unit above the kernel maximum, or the control ID being stale after kernel state changes.","commonSituations":"Config tun.dev set to a specific utunN that macOS already allocated (e.g. utun3 used by VPN/icloud private relay); leftover utun from a crashed previous nebula instance.","solutions":["Remove tun.dev from config (or leave it unset) so macOS assigns the next available utun unit automatically.","Check `ifconfig` for the utunN device and pick an unused unit if a fixed name is required.","Kill any stale nebula/VPN processes holding the utun unit and retry.","Use a lower unit number (macOS reserves utun0-utun3 for system services)."],"exampleFix":"// before (nebula.yml)\ntun:\n  dev: utun3\n// after\ntun:\n  dev: utun50  # or omit 'dev' entirely to auto-assign","handlingStrategy":"validation","validationCode":"// before starting nebula, if tun.dev is pinned, verify it is free:\nout, _ := exec.Command(\"ifconfig\", devName).Output()\nif len(out) > 0 {\n    return fmt.Errorf(\"interface %s already exists; unset tun.dev to auto-assign\", devName)\n}","typeGuard":null,"tryCatchPattern":"if err := start(); err != nil && strings.Contains(err.Error(), \"SYS_CONNECT\") {\n    // utun unit likely in use: clear tun.dev and retry with auto-assigned unit\n}","preventionTips":["Leave tun.dev unset on macOS so the kernel assigns a free utun unit","Avoid utun0-utun3 which macOS system services reserve","Clean up stale utun devices after crashes before restarting"],"tags":["macos","darwin","utun","connect","interface-in-use"],"backgroundTag":"utun-interface-in-use","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"}