lima-vm/lima · error

failed to replace original with raw image: %w

Error message

failed to replace original with raw image: %w

What it means

After removing any stale entry, ensureRawInCache atomically renames imgconv/raw.tmp to imgconv/raw. If os.Rename fails (raw.tmp vanished, cross-device rename, permissions), the converted image cannot replace the cached original and this error is returned. The defer os.Remove(rawPathTmp) cleans up the tmp file afterwards.

Source

Thrown at pkg/downloader/downloader.go:500

		return "", "", fmt.Errorf("failed to open raw tmp file %q: %w", rawPathTmp, err)
	}
	fi, err := rawTmpF.Stat()
	if err != nil {
		_ = rawTmpF.Close()
		return "", "", fmt.Errorf("failed to stat raw tmp file %q: %w", rawPathTmp, err)
	}
	if err := diskUtil.MakeSparse(ctx, rawTmpF, fi.Size()); err != nil {
		logrus.WithError(err).Warnf("Failed to make %q sparse (non-fatal)", rawPathTmp)
	}
	if err := rawTmpF.Close(); err != nil {
		return "", "", fmt.Errorf("failed to close raw tmp file %q: %w", rawPathTmp, err)
	}

	if err := os.Remove(rawImgConvPath); err != nil && !errors.Is(err, os.ErrNotExist) {
		return "", "", fmt.Errorf("failed to remove stale raw image %q: %w", rawImgConvPath, err)
	}
	if err := os.Rename(rawPathTmp, rawImgConvPath); err != nil {
		return "", "", fmt.Errorf("failed to replace original with raw image: %w", err)
	}

	algo := digest.Canonical
	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) {

View on GitHub (pinned to dd909d0973)

Solutions

  1. Avoid running multiple limactl downloads of the same image concurrently against the same cache; retry sequentially
  2. Verify the cache directory is on a single local filesystem so rename is atomic
  3. Check directory write permissions on the imgconv folder and fix with chown/chmod
  4. Clear the affected cache entry (<hash> dir) and re-download to get a consistent state
Defensive patterns

Strategy: retry

Try / catch

err := downloadOnce()
if err != nil && strings.Contains(err.Error(), "failed to replace original with raw image") {
    time.Sleep(2 * time.Second)
    err = downloadOnce() // racing tmp cleanup is transient; second attempt usually succeeds
}

Prevention

When it happens

Trigger: os.Rename(rawPathTmp, rawImgConvPath) returns ENOENT (tmp deleted concurrently by another downloader process), EXDEV (cache spans filesystems), or EACCES on the directory.

Common situations: Two limactl processes downloading the same image race and one's deferred cleanup deletes the other's raw.tmp; cache directory placed on a filesystem where rename across the imgconv dir fails; antivirus/indexers removing tmp files.

Related errors


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