LykosAI/StabilityMatrix · error · IOException
Unable to delete junction point.
Error message
Unable to delete junction point.
What it means
Delete() first removes the reparse point via DeviceIoControl, then calls Directory.Delete(junctionPoint). If the final Directory.Delete throws IOException (directory not empty, locked, or on a deleted target), the method wraps it in this IOException. It means the junction reparse data was removed but the now-plain directory itself could not be deleted.
Solutions
- Check that the directory under the junction path is actually empty (e.g. Directory.EnumerateFileSystemEntries) before calling Delete; move out or delete any contents
- Close any process holding handles inside the junction (apps, editors, antivirus scans) and retry
- Call Junction.Exists(path) first to confirm it is still a junction; if the reparse point was already removed, use Directory.Delete directly
- Catch IOException, inspect the inner exception, and clean up the leftover empty/plain directory manually
Example fix
// before
Junction.Delete(path); // IOException if dir not empty
// after
if (Junction.Exists(path))
{
foreach (var f in Directory.EnumerateFileSystemEntries(path))
throw new IOException($"Junction target not empty: {f}");
Junction.Delete(path);
}
else
{
Directory.Delete(path, recursive: true);
} Defensive patterns
Strategy: try-catch
Validate before calling
if (!Directory.Exists(path)) throw new FileNotFoundException(path);
bool isJunction = Junction.Exists(path);
bool empty = !Directory.EnumerateFileSystemEntries(path).Any();
if (!isJunction || !empty) throw new InvalidOperationException("Path must be an empty junction point."); Type guard
static bool IsDeletableJunction(string path) =>
Directory.Exists(path) && Junction.Exists(path) && !Directory.EnumerateFileSystemEntries(path).Any(); Try / catch
try
{
Junction.Delete(path);
}
catch (IOException ex)
{
// inner exception tells whether dir was locked/not empty
logger.LogError(ex.InnerException ?? ex, "Failed to delete junction {Path}", path);
if (Directory.Exists(path) && !Junction.Exists(path))
Directory.Delete(path, recursive: false); // reparse already removed
} Prevention
- Always call Junction.Exists before Delete
- Ensure no apps/services hold files under the junction (close editors, pause AV scans)
- Empty the junction's contents before deleting
- Handle the leftover-directory case: after a failed delete, check whether the reparse point is already gone and clean up with Directory.Delete
When it happens
Trigger: Calling Junction.Delete on a path whose underlying directory contains files placed inside it after the junction was created, or where the directory handle is held open by another process, or where the target was removed concurrently so the directory state is inconsistent.
Common situations: Deleting a shared-models junction while an app (e.g. ComfyUI) still has files open inside it; antivirus or an indexer holding the directory; a partially-failed previous Delete attempt leaving a plain non-empty directory; running on a network drive where reparse deletion half-completed.
Related errors
- Failed to delete junction point
- Target path does not exist or is not a directory
- Directory already exists and overwrite parameter is false.
- Path is not a junction point.
- Failed to delete junction point
AI-assisted analysis of LykosAI/StabilityMatrix@af93d6ef57 (2026-09-12).
Data as JSON: /api/errors/50fa4da85e7674eb.
Report an issue: GitHub.
Appendix: source
Thrown at StabilityMatrix.Core/ReparsePoints/Junction.cs:160
Debug.WriteLine($"bytesReturned: {bytesReturned}");
if (!result)
{
ThrowLastWin32Error($"Unable to delete junction point {junctionPoint}");
}
}
finally
{
Marshal.FreeHGlobal(inBuffer);
}
try
{
Directory.Delete(junctionPoint);
}
catch (IOException ex)
{
throw new IOException("Unable to delete junction point.", ex);
}
}
/// <summary>
/// Determines whether the specified path exists and refers to a junction point.
/// </summary>
/// <param name="path">The junction point path</param>
/// <returns>True if the specified path represents a junction point</returns>
/// <exception cref="IOException">Thrown if the specified path is invalid
/// or some other error occurs</exception>
public static bool Exists(string path)
{
if (!Directory.Exists(path)) return false;
using var handle = OpenReparsePoint(path, Win32FileAccess.GenericRead);
var target = InternalGetTarget(handle);
return target != null;
}View on GitHub (pinned to af93d6ef57)