ginuerzh/gost · error

%s: %v

Error message

%s: %v

What it means

On BSD/macOS, createTun brings the newly created TUN interface up via `ifconfig <name> inet <addr> mtu <mtu> up`; if ifconfig fails (non-zero exit) the error is wrapped with the full command line. It is returned as the named error of createTun, so interface creation appears to fail even though the device node may already exist.

Source

Thrown at tuntap_unix.go:38

	}

	ifce, err := water.New(water.Config{
		DeviceType: water.TUN,
	})
	if err != nil {
		return
	}

	mtu := cfg.MTU
	if mtu <= 0 {
		mtu = DefaultMTU
	}

	cmd := fmt.Sprintf("ifconfig %s inet %s mtu %d up", ifce.Name(), cfg.Addr, mtu)
	log.Log("[tun]", cmd)
	args := strings.Split(cmd, " ")
	if er := exec.Command(args[0], args[1:]...).Run(); er != nil {
		err = fmt.Errorf("%s: %v", cmd, er)
		return
	}

	if err = addTunRoutes(ifce.Name(), cfg.Routes...); err != nil {
		return
	}

	itf, err = net.InterfaceByName(ifce.Name())
	if err != nil {
		return
	}

	conn = &tunTapConn{
		ifce: ifce,
		addr: &net.IPAddr{IP: ip},
	}
	return
}

View on GitHub (pinned to a33fdbf4c9)

Solutions

  1. Run the process as root (sudo) — ifconfig needs privileges to set an address on the interface
  2. Verify cfg.Addr is a valid IPv4 address/prefix in CIDR form
  3. Check the wrapped message: 'permission denied' vs 'invalid argument' vs 'does not exist' to decide between privilege, config, or device problems
  4. Confirm the TUN kext/driver is loaded and the interface exists (`ifconfig <name>` before configure)

Example fix

// before
_, err := tun.CreateTun(tun.Config{Addr: "10.0.0.1/xx", MTU: 1500}) // bad CIDR -> ifconfig fails
// after
_, err := tun.CreateTun(tun.Config{Addr: "10.0.0.1/24", MTU: 1500}) // run with sudo
Defensive patterns

Strategy: validation

Validate before calling

func checkTunCfg(cfg tun.Config) error {
    ip, _, err := net.ParseCIDR(cfg.Addr)
    if err != nil || ip.To4() == nil {
        return fmt.Errorf("tun: Addr must be IPv4 CIDR, got %q", cfg.Addr)
    }
    if cfg.MTU < 68 || cfg.MTU > 65535 {
        return fmt.Errorf("tun: invalid MTU %d", cfg.MTU)
    }
    return nil
}

Type guard

func validIPv4CIDR(s string) bool {
    ip, _, err := net.ParseCIDR(s)
    return err == nil && ip.To4() != nil
}

Try / catch

ifce, err := tun.CreateTun(cfg)
if err != nil {
    if strings.Contains(err.Error(), "permission denied") {
        return fmt.Errorf("re-run with sudo: %w", err)
    }
    if strings.Contains(err.Error(), "does not exist") {
        return fmt.Errorf("tun device missing — load driver: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: Calling createTun on macOS/BSD when the address is invalid, MTU is out of range, the interface does not exist/was destroyed, or the process lacks privileges to configure the interface.

Common situations: Not running as root on macOS (ifconfig needs privileges to set addresses); passing an IPv6 address to a command formatted for `inet` only; devfs/BSD device not created because kext not loaded.

Related errors


AI-assisted analysis of ginuerzh/gost@a33fdbf4c9 (2026-09-02). Data as JSON: /api/errors/16a788eee7563051. Report an issue: GitHub.