lima-vm/lima · error
failed to remove stale raw image %q: %w
Error message
failed to remove stale raw image %q: %w
What it means
Before promoting the freshly converted raw image into place, ensureRawInCache removes any stale existing imgconv/raw file. If os.Remove fails for a reason other than the file not existing, the conversion is aborted with this wrapped error. This is a pre-rename cleanup step guarding the atomic replacement of the cached raw image.
Source
Thrown at pkg/downloader/downloader.go:497
// Ensure the image is sparse to save cache space.
rawTmpF, err := os.OpenFile(rawPathTmp, os.O_RDWR, 0o644)
if err != nil {
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 {View on GitHub (pinned to dd909d0973)
Solutions
- Fix ownership/permissions on the cache imgconv directory: chown/chmod so the current user can delete files
- Ensure no running VM or qemu-img process still uses the cached raw image; stop instances before re-downloading
- Manually remove the stale file/directory (<cacheDir>/download/by-url-sha256/<hash>/imgconv) and retry
- Check for immutable flags (chattr -i) or read-only mounts on the cache volume
Example fix
// before: permission denied removing stale raw image $ ls -l ~/.lima/_cache/download/by-url-sha256/<hash>/imgconv/raw # owned by root // after $ sudo chown -R $(whoami) ~/.lima/_cache # or delete: rm -rf .../imgconv
Defensive patterns
Strategy: validation
Validate before calling
rawImgConvPath := filepath.Join(cacheDir, "download", "by-url-sha256", key, "imgconv", "raw")
if _, err := os.Stat(rawImgConvPath); err == nil {
if err := os.Remove(rawImgConvPath); err != nil {
return fmt.Errorf("cannot clear stale raw image (check perms/locks): %w", err)
}
} Try / catch
if err != nil && strings.Contains(err.Error(), "failed to remove stale raw image") {
// stop VMs, fix ownership, retry
} Prevention
- Run all limactl operations as the same (non-root) user so cache files share one owner
- Stop running VMs before re-downloading the same image
- Avoid placing the cache on NFS or removable media
- Pre-clear the cache entry when you know an image URL changed content
When it happens
Trigger: An old imgconv/raw exists in the cache and os.Remove returns e.g. EACCES/EPERM (read-only dir or file), EBUSY (file held by a running VM/qemu), or EISDIR/immutable attribute — anything besides ErrNotExist.
Common situations: Cache directory or files made read-only by permissions or ownership (e.g. created by root, now run as user); a previous VM process still holds the raw image open; immutable flag set after a crash-recovery tool ran.
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
- failed to remove stale raw digest file %q: %w
- failed to close raw tmp file %q: %w
- failed to replace original with raw image: %w
- failed to calculate digest of raw image: %w
- failed to write raw digest file: %w
AI-assisted analysis of lima-vm/lima@dd909d0973 (2026-09-01).
Data as JSON: /api/errors/e23c966f91495d55.
Report an issue: GitHub.