tailscale/tailscale · warning

stat %q: %v

Error message

stat %q: %v

What it means

Same migration as the other stat error, but inside moveFiles: os.Stat on a source file (in / or /var/cache/tailscale) failed with something other than NotExists. Note this variant uses %v, so it is not errors.Is/As-unwrappable. The error is logged and the move step is abandoned; old files stay where they are.

Source

Thrown at logpolicy/logpolicy.go:388

			_, err := os.Stat(p)
			if os.IsNotExist(err) {
				continue
			} else if err != nil {
				return false, fmt.Errorf("stat %q: %w", p, err)
			}
			return true, nil
		}
		return false, nil
	}
	// move files from d into dir, if they exist.
	moveFiles := func(d string) error {
		for _, file := range files {
			src := filepath.Join(d, file)
			_, err := os.Stat(src)
			if os.IsNotExist(err) {
				continue
			} else if err != nil {
				return fmt.Errorf("stat %q: %v", src, err)
			}
			dst := filepath.Join(dir, file)
			bs, err := exec.Command("mv", src, dst).CombinedOutput()
			if err != nil {
				return fmt.Errorf("mv %q %q: %v (%s)", src, dst, err, bs)
			}
		}
		return nil
	}

	existsInRoot, err := checkExists("/")
	if err != nil {
		logf("checking for configs in /: %v", err)
		return
	}
	existsInCache := false
	cacheDir := os.Getenv("CACHE_DIRECTORY")
	if cacheDir != "" {

View on GitHub (pinned to 6e0912f979)

Solutions

  1. Fix permissions on the reported path so root can stat it, then restart the binary to re-run migration
  2. Manually move/remove the leftover <cmdname>.log* files listed in the path
  3. Safe to ignore: it only delays cleanup of pre-existing log files
Defensive patterns

Strategy: fallback

Try / catch

if _, err := os.Stat(src); err != nil {
	if os.IsNotExist(err) {
		continue
	}
	// non-unwrappable %v message: log and skip this file,
	// migration continues with the rest
	log.Printf("[non-fatal] skipping %s: %v", src, err)
}

Prevention

When it happens

Trigger: moveFiles statting a leftover file that the process cannot access (permission denied, EIO), or a dangling path with EACCES on a parent directory; reached only when old files were detected by checkExists.

Common situations: Leftover tailscale log files from older packages on systems where permissions changed; read-only or failing mounts under /var/cache.

Related errors


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