henrygd/beszel · error
rename
Error message
rename: %w
What it means
After chmod succeeds, downloadFile atomically moves the temp file to its final destination with os.Rename. A wrapped `rename: %w` error means the move failed and the temp file was deleted. Rename typically fails when source and destination are on different filesystems or the destination is not writable.
Solutions
- Ensure the destination directory exists and is writable (sufficient privileges or a user-writable path).
- Set TMPDIR (or the temp path) to a directory on the same filesystem as the destination to avoid EXDEV, or add a copy-based fallback.
- Retry if the cause was a transient lock (antivirus/another process); avoid running multiple instances concurrently.
- Read the wrapped error's errno: ENOENT → create dest dir; EXDEV → same-fs temp; EACCES → fix permissions.
Example fix
// before
if err := os.Rename(tmp, dest); err != nil {
return fmt.Errorf("rename: %w", err)
}
// after
if err := os.Rename(tmp, dest); err != nil {
if errors.Is(err, syscall.EXDEV) {
if cerr := copyFile(tmp, dest); cerr != nil {
return fmt.Errorf("rename: %w", err)
}
} else {
return fmt.Errorf("rename: %w", err)
}
} Defensive patterns
Strategy: try-catch
Validate before calling
// ensure dest dir exists and temp and dest share a filesystem
if err := os.MkdirAll(filepath.Dir(dest), 0o755); err != nil {
return err
}
tmp := filepath.Join(filepath.Dir(dest), ".fetch-tmp") // same device as dest Try / catch
if err := downloadFile(url, dest, sha); err != nil {
if strings.HasPrefix(err.Error(), "rename:") {
log.Printf("rename failed (cross-device or locked dest?): %v", err)
} else {
return err
}
} Prevention
- Create the temp file next to the destination so rename stays on one device.
- MkdirAll the destination directory before download.
- Avoid concurrent runs writing the same destination.
- Check dest is writable before starting (access test).
When it happens
Trigger: os.Rename(tmp, dest) errors: temp dir and dest are on different mounts/devices (EXDEV), dest directory doesn't exist or lacks write permission, dest is locked by another process (Windows), or tmp vanished.
Common situations: TMPDIR on tmpfs while dest is on another disk; installing to a read-only or root-owned directory without privileges; concurrent runs racing over the same dest file; antivirus holding the file open.
Related errors
AI-assisted analysis of henrygd/beszel@b38fb7dafa (2026-08-31).
Data as JSON: /api/errors/1912d13221ff0509.
Report an issue: GitHub.
Appendix: source
Thrown at agent/tools/fetchsmartctl/main.go:120
}
if hasher != nil && shaHex != "" {
cleanSha := strings.ToLower(strings.ReplaceAll(strings.TrimSpace(shaHex), " ", ""))
got := strings.ToLower(hex.EncodeToString(hasher.Sum(nil)))
if got != cleanSha {
os.Remove(tmp)
return fmt.Errorf("hash mismatch: got %s want %s", got, cleanSha)
}
}
// Make executable and move into place
if err := os.Chmod(tmp, 0o755); err != nil {
os.Remove(tmp)
return fmt.Errorf("chmod: %w", err)
}
if err := os.Rename(tmp, dest); err != nil {
os.Remove(tmp)
return fmt.Errorf("rename: %w", err)
}
fmt.Println("smartctl.exe downloaded to", dest)
return nil
}
func fatalf(format string, a ...any) {
fmt.Fprintf(os.Stderr, format+"\n", a...)
os.Exit(1)
}
View on GitHub (pinned to b38fb7dafa)