lima-vm/lima · error

failed to remove stale raw digest file %q: %w

Error message

failed to remove stale raw digest file %q: %w

What it means

Before renaming raw.digest.tmp into place, any pre-existing raw.digest is removed. If os.Remove fails for a reason other than ErrNotExist, the cache update aborts with this error. It prevents a stale digest file from shadowing the new one when rename would otherwise fail or leave inconsistent state.

Source

Thrown at pkg/downloader/downloader.go:519

	}

	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) {
		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)
}

View on GitHub (pinned to dd909d0973)

Solutions

  1. chown/chmod the imgconv directory contents so the current user can delete the digest file
  2. Stop any process holding the digest file open (VMs, sync tools) and retry
  3. Remove the whole cache entry directory manually and re-download
  4. Check and clear immutable flags (chattr -i) on the file

Example fix

// before
$ rm ~/.lima/_cache/download/by-url-sha256/<hash>/imgconv/raw.digest  # EACCES
// after
$ sudo chown -R $(whoami) ~/.lima/_cache && limactl start <instance>
Defensive patterns

Strategy: validation

Validate before calling

digestPath := filepath.Join(cacheDir, "download", "by-url-sha256", key, "imgconv", "raw.digest")
if _, err := os.Stat(digestPath); err == nil {
    if err := os.Remove(digestPath); err != nil {
        return fmt.Errorf("stale digest not removable, fix permissions/locks first: %w", err)
    }
}

Try / catch

if err != nil && strings.Contains(err.Error(), "failed to remove stale raw digest file") {
    // chown -R the cache and stop locking processes before retrying
}

Prevention

When it happens

Trigger: An old imgconv/raw.digest exists and os.Remove returns EACCES/EPERM (read-only or root-owned file), EBUSY (file held open), or an immutable attribute — any non-ErrNotExist failure.

Common situations: Cache files previously written by a privileged run are now undeletable by the normal user; backup or sync software locks digest files on Windows/NFS; manual tampering left odd permissions.

Understand the failure class

Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.

Related errors


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