{"record":{"id":"c21d3a0e13aa0b3f","repo":"LykosAI/StabilityMatrix","slug":"failed-to-delete-directory-directory","errorCode":null,"errorMessage":"Failed to delete directory {directory}","messagePattern":"Failed to delete directory (.+?)","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"StabilityMatrix.Core/Extensions/DirectoryPathExtensions.cs","lineNumber":104,"sourceCode":"            try\n            {\n                filePath.Info.Attributes = FileAttributes.Normal;\n                filePath.Delete();\n            }\n            catch (IOException ex)\n            {\n                throw new IOException($\"Failed to delete file {filePath.FullPath}\", ex);\n            }\n        }\n\n        // Delete this directory\n        try\n        {\n            directory.Delete(false);\n        }\n        catch (IOException ex)\n        {\n            throw new IOException($\"Failed to delete directory {directory}\", ex);\n        }\n    }\n}\n","sourceCodeStart":86,"sourceCodeEnd":108,"githubUrl":"https://github.com/LykosAI/StabilityMatrix/blob/af93d6ef57c01cd890d7e0ad0a9ea8c9fcda3002/StabilityMatrix.Core/Extensions/DirectoryPathExtensions.cs#L86-L108","documentation":"This is the final stage of DeleteVerbose: after recursively clearing subdirectories and files, the directory itself is deleted with directory.Delete(false), and an IOException is wrapped with the directory path. It means the (now supposedly empty) directory could not be removed by the OS.","triggerScenarios":"The leaf/parent directory delete throws IOException — typically because the directory is not actually empty (a race added files), the process cwd or a handle is inside it, or an OS-level I/O error occurred.","commonSituations":"Deleting a package install directory while the application's working directory is set to it; a background process recreating files mid-delete; Windows delayed file-handle release right after deleting children.","solutions":["Ensure no process has its working directory set inside the target directory before deleting","Retry the delete after a short delay to allow OS handle release (common on Windows)","Check for files recreated between enumeration and deletion (race), and re-run the delete","Inspect the inner exception for the exact Win32 error code"],"exampleFix":"// before\ndirectory.Delete(false);\n// after\nfor (var attempt = 0; attempt < 3; attempt++)\n{\n    try { directory.Delete(false); break; }\n    catch (IOException) when (attempt < 2) { Thread.Sleep(200); }\n}","handlingStrategy":"retry","validationCode":"if (Directory.Exists(dir))\n{\n    if (Path.GetFullPath(dir) == Path.GetFullPath(Directory.GetCurrentDirectory()))\n        Directory.SetCurrentDirectory(Path.GetDirectoryName(dir)!);\n    if (Directory.EnumerateFileSystemEntries(dir).Any())\n        Console.WriteLine(\"Directory not empty; rerun recursive delete first\");\n}","typeGuard":null,"tryCatchPattern":"try { DirectoryPathExtensions.DeleteVerbose(dir, logger, ct); }\ncatch (IOException ex)\n{\n    await Task.Delay(300);\n    DirectoryPathExtensions.DeleteVerbose(dir, logger, ct); // single retry after handle release\n}","preventionTips":["Never set the process cwd inside a directory slated for deletion","Allow a short delay between deleting children and the parent","Re-check emptiness before the final directory delete","Log inner-exception Win32 codes for diagnosis"],"tags":["io","filesystem","directory"],"backgroundTag":"file-delete-failed","analyzedSha":"af93d6ef57c01cd890d7e0ad0a9ea8c9fcda3002","analyzedAt":"2026-09-12T19:02:43.389Z","contentChangedAt":"2026-09-12T19:02:43.389Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}