lima-vm/lima · error

failed to rename raw digest file

Error message

failed to rename raw digest file: %w

What it means

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.

Solutions

  1. Retry the operation without concurrent limactl invocations on the same cache; the download lock usually prevents this, but Cached-vs-download mixes can race
  2. Verify write permission on the imgconv directory (chmod/chown)
  3. Clear the cache entry directory and re-download
  4. Keep the cache on one local filesystem so rename stays atomic
Defensive patterns

Strategy: retry

Try / catch

if err != nil && strings.Contains(err.Error(), "failed to rename raw digest file") {
    time.Sleep(2 * time.Second)
    err = downloadOnce() // transient race on the .tmp file resolves on retry
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of lima-vm/lima@dd909d0973 (2026-09-01). Data as JSON: /api/errors/94a33fd34692a418. Report an issue: GitHub.

Appendix: source

Thrown at pkg/downloader/downloader.go:522

	if originalDigest != "" {
		algo = originalDigest.Algorithm()
	}
	rawDigest, err := calculateFileDigest(rawImgConvPath, algo)
	if err != nil {
		return "", "", fmt.Errorf("failed to calculate digest of raw image: %w", err)
	}

	rawDigestPath := filepath.Join(imgConvPath, "raw.digest")
	rawDigestPathTmp := rawDigestPath + ".tmp"
	defer os.Remove(rawDigestPathTmp)
	if err := os.WriteFile(rawDigestPathTmp, []byte(rawDigest.String()), 0o644); err != nil {
		return "", "", fmt.Errorf("failed to write raw digest file: %w", err)
	}
	if err := os.Remove(rawDigestPath); err != nil && !errors.Is(err, os.ErrNotExist) {
		return "", "", fmt.Errorf("failed to remove stale raw digest file %q: %w", rawDigestPath, err)
	}
	if err := os.Rename(rawDigestPathTmp, rawDigestPath); err != nil {
		return "", "", fmt.Errorf("failed to rename raw digest file: %w", err)
	}

	return rawImgConvPath, rawDigest, nil
}

func calculateFileDigest(path string, algo digest.Algorithm) (digest.Digest, error) {
	f, err := os.Open(path)
	if err != nil {
		return "", err
	}
	defer f.Close()

	return algo.FromReader(f)
}

// Cached checks if the remote resource is in the cache.
//
// Download caches the remote resource if WithCache or WithCacheDir option is specified.

View on GitHub (pinned to dd909d0973)