tailscale/tailscale · error

running %v: %w, out=%s, err=%s

Error message

running %v: %w, out=%s, err=%s

What it means

This is dirRunner.output's diagnostic wrapper for a child command that ran and exited non-zero: it prints the argv, wrapped error, captured stdout (out=) and the child's stderr (err=). Every git failure inside mkversion (finding git root, getting hash/date, cache rev-parse, etc.) surfaces through this wrapper and is then re-wrapped by the caller - so this message is where the real git diagnostics live.

Source

Thrown at version/mkversion/mkversion.go:502

type dirRunner string

func (r dirRunner) output(prog string, args ...string) (string, error) {
	cmd := exec.Command(prog, args...)
	// Sometimes, our binaries end up running in a world where
	// GO111MODULE=off, because x/tools/go/packages disables Go
	// modules on occasion and then runs other Go code. This breaks
	// executing "go mod edit", which requires that Go modules be
	// enabled.
	//
	// Since nothing we do here ever wants Go modules to be turned
	// off, force it on here so that we can read module data
	// regardless of the environment.
	cmd.Env = append(os.Environ(), "GO111MODULE=on")
	cmd.Dir = string(r)
	out, err := cmd.Output()
	if err != nil {
		if ee, ok := err.(*exec.ExitError); ok {
			return "", fmt.Errorf("running %v: %w, out=%s, err=%s", cmd.Args, err, out, ee.Stderr)
		}
		return "", fmt.Errorf("running %v: %w, %s", cmd.Args, err, out)
	}
	return strings.TrimSpace(string(out)), nil
}

func (r dirRunner) ok(prog string, args ...string) bool {
	cmd := exec.Command(prog, args...)
	cmd.Dir = string(r)
	return cmd.Run() == nil
}

View on GitHub (pinned to 6e0912f979)

Solutions

  1. Copy the argv shown in the message and run it manually in the same directory (note commands against the cache run with cwd = cache dir)
  2. Read the err=<stderr> field - it contains git's actual fatal message
  3. Fix the underlying condition per that message (commit, ref, network, permissions)
Defensive patterns

Strategy: try-catch

Type guard

func isSubprocessExitError(err error) bool {
	var ee *exec.ExitError
	for e := err; e != nil; e = errors.Unwrap(e) {
		if errors.As(e, &ee) {
			return true
		}
		if strings.Contains(e.Error(), "running [") {
			return true
		}
	}
	return false
}

Try / catch

v, err := mkversion.InfoFrom(dir)
if err != nil {
	// The message embeds argv + out= + err=<git stderr>.
	// Extract and surface the stderr field for actionable diagnostics.
	if i := strings.Index(err.Error(), "err="); i != -1 {
		return fmt.Errorf("git failed: %s", err.Error()[i:])
	}
	return err
}

Prevention

When it happens

Trigger: Any git subcommand failing: rev-parse in a non-repo, rev-parse HEAD with unborn branch, cat-file/rev-list on missing refs in the cache, fetch while offline. Recognizable by '*exec.ExitError' semantics and the err= field carrying git's stderr.

Common situations: Triaging any mkversion build failure; the out=/err= fields tell you whether it is repo state, refs, or network.

Related errors


AI-assisted analysis of tailscale/tailscale@6e0912f979 (2026-08-18). Data as JSON: /api/errors/d97cdbd7aea6b55e. Report an issue: GitHub.