LykosAI/StabilityMatrix · error · IOException

Failed to delete file

Error message

Failed to delete file {filePath}

What it means

This IOException is thrown by PackageManagerViewModel.DeleteDirectory when an individual file inside the package directory cannot be deleted. The routine clears file attributes (File.SetAttributes to Normal, to strip ReadOnly/Hidden) and then calls File.Delete; if the OS refuses with an IOException, the file path is wrapped in this message. The async caller retries up to 3 times with exponential backoff via Polly because deletions typically fail transiently when another process still holds an open handle.

Solutions

  1. Stop every process using the package (the package server/venv, editors, terminals) and retry the delete.
  2. Check the inner exception's HResult to identify the cause: 0x80070020 (sharing violation) means a process holds the file; 0x80070005 means access denied; 0x8007108D means the file is a cloud placeholder.
  3. Exclude the Stability Matrix packages folder from antivirus/backup/OneDrive sync and retry.
  4. Ensure the drive is not read-only or full, and check file permissions/ownership on the package directory.
  5. If retries keep failing, reboot (releases leaked handles) and delete the package again, or remove it manually in Explorer.

Example fix

// caller: stop processes before deleting, and surface the inner exception for diagnosis
try
{
    await StopPackageProcesses(); // kill running package server before delete
    await DeleteDirectoryAsync(packagePath);
}
catch (IOException ex)
{
    logger.LogError(ex, "Could not delete {File}: {Reason}", ex.Message, ex.InnerException?.HResult);
    NotifyUser("Close programs using this package and try again.");
}
Defensive patterns

Strategy: try-catch

Validate before calling

if (!Directory.Exists(packagePath)) return;
// best-effort pre-check: no file in the tree is currently open for write
foreach (var f in Directory.EnumerateFiles(packagePath, "*", SearchOption.AllDirectories))
{
    try { using var fs = File.Open(f, FileMode.Open, FileAccess.Read, FileShare.None); }
    catch (IOException) { throw new InvalidOperationException($"File is in use: {f}"); }
}

Type guard

static bool IsDeletableFile(string path) =>
    File.Exists(path) && !new FileInfo(path).Attributes.HasFlag(FileAttributes.ReparsePoint);

Try / catch

try
{
    await DeleteDirectoryAsync(packagePath);
}
catch (IOException ex)
{
    var hresult = ex.InnerException?.HResult;
    if (hresult == unchecked((int)0x80070020))
        NotifyUser("A file is open in another program. Close it and retry.");
    else if (hresult == unchecked((int)0x80070005))
        NotifyUser("Access denied. Run as admin or fix folder permissions.");
    else
        logger.LogError(ex, "Failed to delete {Path}", packagePath);
}

Prevention

When it happens

Trigger: File.Delete(filePath) throws IOException while recursively deleting a package directory: the file is locked/open in another process (running package executable, console window, editor, antivirus scanner), the file is on a network/synced drive (OneDrive/Dropbox placeholder), the disk is full or the media is write-protected, or clearing attributes with File.SetAttributes itself fails on inaccessible storage.

Common situations: Deleting a ComfyUI/A1111 package while its server process is still running and has python files or model checkpoints open; a shared venv or model file being scanned by Windows Defender; the package lives in a OneDrive 'cloud files' folder where hydration makes Delete fail; a long path (>260 chars) deep in a package tree.

Related errors


AI-assisted analysis of LykosAI/StabilityMatrix@af93d6ef57 (2026-09-12). Data as JSON: /api/errors/a3b3fa9e6d688a40. Report an issue: GitHub.

Appendix: source

Thrown at StabilityMatrix/ViewModels/PackageManagerViewModel.cs:266

        }
        // Recursively delete all subdirectories
        var subdirectoryEntries = Directory.GetDirectories(targetDirectory);
        foreach (var subdirectoryPath in subdirectoryEntries)
        {
            DeleteDirectory(subdirectoryPath);
        }
        // Delete all files in the directory
        var fileEntries = Directory.GetFiles(targetDirectory);
        foreach (var filePath in fileEntries)
        {
            try
            {
                File.SetAttributes(filePath, FileAttributes.Normal);
                File.Delete(filePath);
            }
            catch (IOException ex)
            {
                throw new IOException($"Failed to delete file {filePath}", ex);
            }
        }
        // Delete the target directory itself
        try
        {
            Directory.Delete(targetDirectory, false);
        }
        catch (IOException ex)
        {
            throw new IOException($"Failed to delete directory {targetDirectory}", ex);
        }
    }

    private async Task UpdateSelectedPackage()
    {
        var package = packageFactory.FindPackageByName(SelectedPackage?.PackageName ?? string.Empty);
        if (package == null)
        {

View on GitHub (pinned to af93d6ef57)