{"record":{"id":"94a33fd34692a418","repo":"lima-vm/lima","slug":"failed-to-rename-raw-digest-file-w","errorCode":null,"errorMessage":"failed to rename raw digest file: %w","messagePattern":"failed to rename raw digest file: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/downloader/downloader.go","lineNumber":522,"sourceCode":"\tif originalDigest != \"\" {\n\t\talgo = originalDigest.Algorithm()\n\t}\n\trawDigest, err := calculateFileDigest(rawImgConvPath, algo)\n\tif err != nil {\n\t\treturn \"\", \"\", fmt.Errorf(\"failed to calculate digest of raw image: %w\", err)\n\t}\n\n\trawDigestPath := filepath.Join(imgConvPath, \"raw.digest\")\n\trawDigestPathTmp := rawDigestPath + \".tmp\"\n\tdefer os.Remove(rawDigestPathTmp)\n\tif err := os.WriteFile(rawDigestPathTmp, []byte(rawDigest.String()), 0o644); err != nil {\n\t\treturn \"\", \"\", fmt.Errorf(\"failed to write raw digest file: %w\", err)\n\t}\n\tif err := os.Remove(rawDigestPath); err != nil && !errors.Is(err, os.ErrNotExist) {\n\t\treturn \"\", \"\", fmt.Errorf(\"failed to remove stale raw digest file %q: %w\", rawDigestPath, err)\n\t}\n\tif err := os.Rename(rawDigestPathTmp, rawDigestPath); err != nil {\n\t\treturn \"\", \"\", fmt.Errorf(\"failed to rename raw digest file: %w\", err)\n\t}\n\n\treturn rawImgConvPath, rawDigest, nil\n}\n\nfunc calculateFileDigest(path string, algo digest.Algorithm) (digest.Digest, error) {\n\tf, err := os.Open(path)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\tdefer f.Close()\n\n\treturn algo.FromReader(f)\n}\n\n// Cached checks if the remote resource is in the cache.\n//\n// Download caches the remote resource if WithCache or WithCacheDir option is specified.","sourceCodeStart":504,"sourceCodeEnd":540,"githubUrl":"https://github.com/lima-vm/lima/blob/dd909d0973cd84fa35f9e1693181b4585ea616c1/pkg/downloader/downloader.go#L504-L540","documentation":"The final step publishes the raw digest by renaming raw.digest.tmp to raw.digest. If os.Rename fails (tmp file missing, target directory unwritable, cross-device), this error is returned and the conversion result is discarded. The tmp file is cleaned by a deferred os.Remove.","triggerScenarios":"os.Rename(rawDigestPathTmp, rawDigestPath) returns ENOENT (tmp removed by a racing cleanup in another process), EACCES on the imgconv dir, or EXDEV in unusual mount setups.","commonSituations":"Two limactl processes converting the same image concurrently — one's deferred os.Remove(rawDigestPathTmp) deletes the other's tmp file; cache dir permission changes mid-run.","solutions":["Retry the operation without concurrent limactl invocations on the same cache; the download lock usually prevents this, but Cached-vs-download mixes can race","Verify write permission on the imgconv directory (chmod/chown)","Clear the cache entry directory and re-download","Keep the cache on one local filesystem so rename stays atomic"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err != nil && strings.Contains(err.Error(), \"failed to rename raw digest file\") {\n    time.Sleep(2 * time.Second)\n    err = downloadOnce() // transient race on the .tmp file resolves on retry\n}","preventionTips":["Serialize limactl invocations that touch the same image URL","Keep cache directory permissions stable during runs","Don't manually clean the cache while downloads are in flight","Use one filesystem for the whole cache tree"],"tags":["go","filesystem","cache","race-condition"],"backgroundTag":"rename-atomic-replace-failed","analyzedSha":"dd909d0973cd84fa35f9e1693181b4585ea616c1","analyzedAt":"2026-09-01T14:24:59.842Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}