ginuerzh/gost · error

%s: %v

Error message

%s: %v

What it means

exeCmd runs a shell command built as a single string (split on spaces) and wraps any non-zero exit or spawn failure with the full command line and the underlying error. This library (tuntap) configures TUN/TAP interfaces by shelling out to system tools, so any failure of those tools surfaces as this wrapped error.

Source

Thrown at tuntap_linux.go:153

			continue
		}
		cmd := fmt.Sprintf("ip route add %s via %s dev %s", route, gw, ifName)
		log.Logf("[tap] %s", cmd)

		args := strings.Split(cmd, " ")
		if er := exec.Command(args[0], args[1:]...).Run(); er != nil {
			log.Logf("[tap] %s: %v", cmd, er)
		}
	}
	return nil
}

func exeCmd(cmd string) error {
	log.Log(cmd)

	args := strings.Split(cmd, " ")
	if err := exec.Command(args[0], args[1:]...).Run(); err != nil {
		return fmt.Errorf("%s: %v", cmd, err)
	}

	return nil
}

View on GitHub (pinned to a33fdbf4c9)

Solutions

  1. Run the program as root or with CAP_NET_ADMIN so the networking command can succeed
  2. Install the required networking tool (iproute2) in the environment/container
  3. Check the wrapped %v message: 'executable file not found' means the tool is missing, 'operation not permitted' means insufficient privileges
  4. Print cfg values (Addr, MTU, Routes) to confirm no malformed input produced a broken command string

Example fix

// before
if err := exeCmd("ip addr add 10.0.0.1/24 dev tun0"); err != nil { ... } // run as non-root fails
// after
// run binary as root: sudo ./app  (or grant: setcap cap_net_admin+ep ./app)
Defensive patterns

Strategy: validation

Validate before calling

func canConfigureNet() error {
    if os.Geteuid() != 0 {
        return errors.New("tuntap: needs root/CAP_NET_ADMIN")
    }
    if _, err := exec.LookPath("ip"); err != nil {
        return fmt.Errorf("tuntap: iproute2 missing: %w", err)
    }
    return nil
}

Type guard

func cmdToolExists(name string) bool { _, err := exec.LookPath(name); return err == nil }

Try / catch

if err := tun.CreateTun(cfg); err != nil {
    var ee *exec.ExitError
    if errors.As(err, &ee) {
        log.Printf("netsetup failed: %s; stderr: %s", err, ee.Stderr)
    }
    if strings.Contains(err.Error(), "not found") { /* install tool */ }
    if strings.Contains(err.Error(), "operation not permitted") { /* request privileges */ }
}

Prevention

When it happens

Trigger: exeCmd is called from createTun/createTap with a malformed command string, a missing binary (exec: "ip": executable file not found), or the command exits non-zero (e.g. permission denied configuring the interface).

Common situations: Running without root/CAP_NET_ADMIN; the required tool (e.g. `ip`) not installed on the Linux image (slim containers); interface name or CIDR containing characters that break the naive strings.Split(cmd, " ") parsing.

Related errors


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