JosefNemec/Playnite · warning · IOException

Failed to delete {path}

Error message

Failed to delete {path}

What it means

Thrown by FileSystem.DeleteFileSafe after retryAttempts (default 5) consecutive IOExceptions from File.Delete, each retry sleeping 500ms. IMPORTANT: UnauthorizedAccessException is caught separately and returns SILENTLY (no throw), so this exception only fires for IOException-class failures; the inner IOException holds the real reason.

Source

Thrown at source/Playnite/Common/FileSystem.cs:322

                try
                {
                    File.Delete(path);
                    return;
                }
                catch (IOException exc)
                {
                    logger.Debug($"Can't detele file, trying again. {path}");
                    ioException = exc;
                    Task.Delay(500).Wait();
                }
                catch (UnauthorizedAccessException exc)
                {
                    logger.Error(exc, $"Can't detele file, UnauthorizedAccessException. {path}");
                    return;
                }
            }

            throw new IOException($"Failed to delete {path}", ioException);
        }

        public static long GetFreeSpace(string drivePath)
        {
            var root = Path.GetPathRoot(drivePath);
            var drive = DriveInfo.GetDrives().FirstOrDefault(a => a.RootDirectory.FullName.Equals(root, StringComparison.OrdinalIgnoreCase)); ;
            if (drive != null)
            {
                return drive.AvailableFreeSpace;
            }
            else
            {
                return 0;
            }
        }

        public static long GetFileSize(string path)
        {

View on GitHub (pinned to 5911f4e964)

Solutions

  1. Close/release handles (image streams, indexes) that reference the file before deleting.
  2. Re-check with File.Exists after the call — a pending delete may succeed later.
  3. Inspect ex.InnerException for the underlying Win32 error.
  4. If a permission failure is expected, know that UnauthorizedAccessException returns silently here — check existence afterward to confirm.
  5. Exclude the folder from AV to remove scan-window locks.

Example fix

// before
FileSystem.DeleteFileSafe(path);

// after — release handles, then best-effort delete with existence check
imgSource = null; // release any image handle
FileSystem.DeleteFileSafe(path);
if (File.Exists(path)) logger.Warn($"Delete pending or blocked: {path}");
Defensive patterns

Strategy: try-catch

Validate before calling

if (!File.Exists(path)) return; // nothing to do

Try / catch

try { FileSystem.DeleteFileSafe(path); }
catch (IOException ex) { logger.Warn(ex.InnerException ?? ex, $"delete blocked {path}"); }
// NOTE: UnauthorizedAccessException is swallowed internally; verify with File.Exists

Prevention

When it happens

Trigger: File.Delete raising IOException for the full retry window because another process holds the file open; AV scanning the file during delete; pending delete blocked by an open handle.

Common situations: Cleaning up temp/cover/cache files still referenced by an image control or scanner; deleting a file on a slow network share; file enqueued for delete by Windows but not yet removed.

Related errors


AI-assisted analysis of JosefNemec/Playnite@5911f4e964 (2026-08-13). Data as JSON: /api/errors/e98b4d5dbb4ea4c9. Report an issue: GitHub.