{"record":{"id":"3aafc3c707412bb3","repo":"abiosoft/colima","slug":"error-finalizing-download-w","errorCode":null,"errorMessage":"error finalizing download: %w","messagePattern":"error finalizing download: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"util/downloader/download.go","lineNumber":141,"sourceCode":"\t\treturn fmt.Errorf(\"error preparing cache dir: %w\", err)\n\t}\n\n\tif err := fileDownloader.Download(r, cacheDownloadingFilename); err != nil {\n\t\treturn err\n\t}\n\n\t// validate download if SHA is present\n\tif r.SHA != nil {\n\t\tif err := r.SHA.validateDownload(r.URL, cacheDownloadingFilename); err != nil {\n\t\t\t// move file to allow subsequent re-download\n\t\t\t_ = os.Rename(cacheDownloadingFilename, cacheDownloadingFilename+\".invalid\")\n\t\t\treturn fmt.Errorf(\"error validating SHA sum for '%s': %w\", path.Base(r.URL), err)\n\t\t}\n\t}\n\n\t// move completed download to final location\n\tif err := os.Rename(cacheDownloadingFilename, CacheFilename(r.URL)); err != nil {\n\t\treturn fmt.Errorf(\"error finalizing download: %w\", err)\n\t}\n\n\treturn nil\n}\n\nfunc (d downloader) saveResumeInfo(url, etag string, bytesWritten int64) {\n\tinfo := ResumeInfo{ETag: etag, BytesWritten: bytesWritten}\n\tdata, _ := json.Marshal(info)\n\t_ = os.WriteFile(d.resumeInfoPath(url), data, 0644)\n}\n\nfunc (d downloader) hasCache(url string) bool {\n\t_, err := os.Stat(CacheFilename(url))\n\treturn err == nil\n}\n","sourceCodeStart":123,"sourceCodeEnd":157,"githubUrl":"https://github.com/abiosoft/colima/blob/c3a5f9184d83a197184f897a9f07eb3c01b3bc88/util/downloader/download.go#L123-L157","documentation":"The download finished and passed validation, but the final os.Rename of <sha256-of-url>.downloading to the cache filename failed. Both names live in the same directory, so this is a local rename; typical causes are a non-writable caches directory (the existing .downloading partial is reused for resume, so earlier create checks are skipped), the partial vanishing mid-run, or a destination created by a concurrent process.","triggerScenarios":"The caches directory exists (MkdirAll no-ops) but is not writable for the current user; a stale root-owned .downloading partial is resumed and then the rename into place fails with EACCES; another colima process or cache cleaner removed the partial between download and rename (ENOENT).","commonSituations":"Mixing sudo and non-sudo colima runs leaving root-owned cache files; two instances downloading the same URL concurrently; antivirus/file watchers briefly locking files on macOS.","solutions":["Clear the cached entry (final filename and .downloading suffix) and retry","Fix ownership and permissions of the caches directory so the current user can create and replace files","Avoid concurrent downloads sharing one cache dir","Read the wrapped error: EACCES/EPERM means perms, ENOENT means a concurrent cleanup raced you"],"exampleFix":"// before\nif _, err := downloader.Download(host, req); err != nil {\n    return err\n}\n// after: on finalize failure, drop stale entries and retry once\ncache := downloader.CacheFilename(req.URL)\ncacheFile, err := downloader.Download(host, req)\nif err != nil && strings.Contains(err.Error(), \"error finalizing download\") {\n    _ = os.Remove(cache)\n    _ = os.Remove(cache + \".downloading\")\n    cacheFile, err = downloader.Download(host, req)\n}\nif err != nil {\n    return err\n}","handlingStrategy":"retry","validationCode":"cache := downloader.CacheFilename(req.URL)\nif fi, err := os.Stat(cache); err == nil && !fi.IsDir() {\n    if err := os.Remove(cache); err != nil {\n        return fmt.Errorf(\"cannot clear stale cache entry: %w\", err)\n    }\n}","typeGuard":null,"tryCatchPattern":"cache := downloader.CacheFilename(req.URL)\ncacheFile, err := downloader.Download(host, req)\nif err != nil && strings.Contains(err.Error(), \"error finalizing download\") {\n    _ = os.Remove(cache)\n    _ = os.Remove(cache + \".downloading\")\n    cacheFile, err = downloader.Download(host, req)\n}\nif err != nil {\n    return err\n}","preventionTips":["Run downloads as one consistent user to avoid root-owned cache entries","Serialize downloads that share the cache dir (lock file or sequential runs)","Treat EACCES/EPERM in the wrapped error as a permissions fix, not a retry case"],"tags":["filesystem","cache","rename","permissions"],"backgroundTag":null,"analyzedSha":"c3a5f9184d83a197184f897a9f07eb3c01b3bc88","analyzedAt":"2026-08-15T18:58:08.334Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}