{"record":{"id":"1912d13221ff0509","repo":"henrygd/beszel","slug":"rename-w","errorCode":null,"errorMessage":"rename: %w","messagePattern":"rename: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"agent/tools/fetchsmartctl/main.go","lineNumber":120,"sourceCode":"\t}\n\n\tif hasher != nil && shaHex != \"\" {\n\t\tcleanSha := strings.ToLower(strings.ReplaceAll(strings.TrimSpace(shaHex), \" \", \"\"))\n\t\tgot := strings.ToLower(hex.EncodeToString(hasher.Sum(nil)))\n\t\tif got != cleanSha {\n\t\t\tos.Remove(tmp)\n\t\t\treturn fmt.Errorf(\"hash mismatch: got %s want %s\", got, cleanSha)\n\t\t}\n\t}\n\n\t// Make executable and move into place\n\tif err := os.Chmod(tmp, 0o755); err != nil {\n\t\tos.Remove(tmp)\n\t\treturn fmt.Errorf(\"chmod: %w\", err)\n\t}\n\tif err := os.Rename(tmp, dest); err != nil {\n\t\tos.Remove(tmp)\n\t\treturn fmt.Errorf(\"rename: %w\", err)\n\t}\n\n\tfmt.Println(\"smartctl.exe downloaded to\", dest)\n\treturn nil\n}\n\nfunc fatalf(format string, a ...any) {\n\tfmt.Fprintf(os.Stderr, format+\"\\n\", a...)\n\tos.Exit(1)\n}\n","sourceCodeStart":102,"sourceCodeEnd":131,"githubUrl":"https://github.com/henrygd/beszel/blob/b38fb7dafa60812cc22e6a84ce313e94f1ce0a32/agent/tools/fetchsmartctl/main.go#L102-L131","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nif err := os.Rename(tmp, dest); err != nil {\n\treturn fmt.Errorf(\"rename: %w\", err)\n}\n// after\nif err := os.Rename(tmp, dest); err != nil {\n\tif errors.Is(err, syscall.EXDEV) {\n\t\tif cerr := copyFile(tmp, dest); cerr != nil {\n\t\t\treturn fmt.Errorf(\"rename: %w\", err)\n\t\t}\n\t} else {\n\t\treturn fmt.Errorf(\"rename: %w\", err)\n\t}\n}","handlingStrategy":"try-catch","validationCode":"// ensure dest dir exists and temp and dest share a filesystem\nif err := os.MkdirAll(filepath.Dir(dest), 0o755); err != nil {\n\treturn err\n}\ntmp := filepath.Join(filepath.Dir(dest), \".fetch-tmp\") // same device as dest","typeGuard":null,"tryCatchPattern":"if err := downloadFile(url, dest, sha); err != nil {\n\tif strings.HasPrefix(err.Error(), \"rename:\") {\n\t\tlog.Printf(\"rename failed (cross-device or locked dest?): %v\", err)\n\t} else {\n\t\treturn err\n\t}\n}","preventionTips":["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)."],"tags":["go","filesystem","rename","installation"],"backgroundTag":"rename-cross-device","analyzedSha":"b38fb7dafa60812cc22e6a84ce313e94f1ce0a32","analyzedAt":"2026-08-31T15:10:10.149Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}