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
- Fix permissions on the reported path so root can stat it, then restart the binary to re-run migration
- Manually move/remove the leftover <cmdname>.log* files listed in the path
- 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
- Ensure the migration source dirs (/ and /var/cache/tailscale) remain stat-able by root
- Clean up pre-1.x tailscale log files manually if the environment forbids access
- Remember this path only runs as root on linux/freebsd/openbsd during upgrade migration
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
- stat %q: %w
- mv %q %q: %v (%s)
- failed creating systemd user dir: %w
- unable to make tmpDir: %w
- failed extracting the new tailscale binary from %q: %w
AI-assisted analysis of tailscale/tailscale@6e0912f979 (2026-08-18).
Data as JSON: /api/errors/cd29a050283beb4c.
Report an issue: GitHub.