slackhq/nebula · error

SYS_CONNECT: %v

Error message

SYS_CONNECT: %v

What it means

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.

Source

Thrown at overlay/tun_darwin.go:110

	fd, err := unix.Socket(unix.AF_SYSTEM, unix.SOCK_DGRAM, unix.AF_SYS_CONTROL)
	if err != nil {
		return nil, fmt.Errorf("system socket: %v", err)
	}

	var ctlInfo = &unix.CtlInfo{}
	copy(ctlInfo.Name[:], utunControlName)

	err = unix.IoctlCtlInfo(fd, ctlInfo)
	if err != nil {
		return nil, fmt.Errorf("CTLIOCGINFO: %v", err)
	}

	err = unix.Connect(fd, &unix.SockaddrCtl{
		ID:   ctlInfo.Id,
		Unit: uint32(ifIndex) + 1,
	})
	if err != nil {
		return nil, fmt.Errorf("SYS_CONNECT: %v", err)
	}

	name, err = unix.GetsockoptString(fd, unix.AF_SYS_CONTROL, _UTUN_OPT_IFNAME)
	if err != nil {
		return nil, fmt.Errorf("failed to retrieve tun name: %w", err)
	}

	err = unix.SetNonblock(fd, true)
	if err != nil {
		return nil, fmt.Errorf("SetNonblock: %v", err)
	}

	t := &tun{
		f:           os.NewFile(uintptr(fd), ""),
		Device:      name,
		vpnNetworks: vpnNetworks,
		DefaultMTU:  c.GetInt("tun.mtu", DefaultMTU),
		l:           l,

View on GitHub (pinned to dd8f660c0a)

Solutions

  1. Remove tun.dev from config (or leave it unset) so macOS assigns the next available utun unit automatically.
  2. Check `ifconfig` for the utunN device and pick an unused unit if a fixed name is required.
  3. Kill any stale nebula/VPN processes holding the utun unit and retry.
  4. Use a lower unit number (macOS reserves utun0-utun3 for system services).

Example fix

// before (nebula.yml)
tun:
  dev: utun3
// after
tun:
  dev: utun50  # or omit 'dev' entirely to auto-assign
Defensive patterns

Strategy: validation

Validate before calling

// before starting nebula, if tun.dev is pinned, verify it is free:
out, _ := exec.Command("ifconfig", devName).Output()
if len(out) > 0 {
    return fmt.Errorf("interface %s already exists; unset tun.dev to auto-assign", devName)
}

Try / catch

if err := start(); err != nil && strings.Contains(err.Error(), "SYS_CONNECT") {
    // utun unit likely in use: clear tun.dev and retry with auto-assigned unit
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of slackhq/nebula@dd8f660c0a (2026-09-03). Data as JSON: /api/errors/ca9f21bb66e42301. Report an issue: GitHub.