peass-ng/PEASS-ng · error · DirectoryNotFoundException

({0}) The target directory is a file, not a directory: [{1}]

Error message

({0}) The target directory is a file, not a directory: [{1}]

What it means

DeleteDirectoryNative throws DirectoryNotFoundException with the formatted message '({0}) The target directory is a file, not a directory: [{1}]' when RemoveDirectory fails with Win32 error ERROR_DIRECTORY and File.ExistsCore confirms the path refers to a file. AlphaFS disambiguates the generic OS error into this specific message so the caller knows the path was a file, not a directory.

Source

Thrown at winPEAS/winPEASexe/winPEAS/3rdParty/AlphaFS/Filesystem/Directory Class/Directory Core Methods/Directory.DeleteDirectoryNative.cs:64

            : NativeMethods.RemoveDirectoryTransacted(pathLp, transaction.SafeHandle);


         var lastError = Marshal.GetLastWin32Error();

         if (!success)
         {
            switch ((uint) lastError)
            {
               case Win32Errors.ERROR_DIR_NOT_EMPTY:
                  // MSDN: .NET 3.5+: IOException: The directory specified by path is not an empty directory. 
                  throw new DirectoryNotEmptyException(pathLp, true);


               case Win32Errors.ERROR_DIRECTORY:
                  // MSDN: .NET 3.5+: DirectoryNotFoundException: Path refers to a file instead of a directory.
                  if (File.ExistsCore(transaction, false, pathLp, PathFormat.LongFullPath))
                     throw new DirectoryNotFoundException(string.Format(CultureInfo.InvariantCulture, "({0}) {1}", lastError, string.Format(CultureInfo.InvariantCulture, Resources.Target_Directory_Is_A_File, pathLp)));
                  break;


               case Win32Errors.ERROR_PATH_NOT_FOUND:
                  if (continueOnNotFound)
                     return;
                  break;


               case Win32Errors.ERROR_SHARING_VIOLATION:
                  // MSDN: .NET 3.5+: IOException: The directory is being used by another process or there is an open handle on the directory.
                  NativeError.ThrowException(lastError, pathLp);
                  break;


               case Win32Errors.ERROR_ACCESS_DENIED:

                  if (attributes == 0)

View on GitHub (pinned to 53fb989abc)

Solutions

  1. Verify the path is a directory before deleting: check fsEntryInfo.IsDirectory or Directory.Exists vs File.Exists.
  2. Use File.Delete instead when the target turns out to be a file.
  3. Catch DirectoryNotFoundException and branch on whether the path is a file to handle both cases.
  4. Fix upstream path construction so the directory path does not include a file segment.

Example fix

// before
Directory.Delete(userPath); // may actually be a file
// after
if (File.Exists(userPath))
    File.Delete(userPath);
else if (Directory.Exists(userPath))
    Directory.Delete(userPath, true);
Defensive patterns

Strategy: type-guard

Validate before calling

var isDir = Directory.Exists(path) && !File.Exists(path);
if (!isDir) throw new InvalidOperationException($"{path} is not a directory");

Type guard

bool IsDirectoryPath(string p) => Directory.Exists(p) && !File.Exists(p);

Try / catch

try { Directory.Delete(path, true); }
catch (DirectoryNotFoundException) {
    if (File.Exists(path)) File.Delete(path);
}

Prevention

When it happens

Trigger: Calling Directory.Delete (via DeleteDirectoryCore) on a path that actually points to a regular file; a junction/reparse target that resolved to a file; path-building logic that appends or normalizes into a file path (e.g. Path.Combine with a file path from config).

Common situations: Config or database stores a path whose trailing segment is a file name; user-supplied path where the item type was not checked; a symlink/junction that points at a file rather than a directory; a file replaced the directory after an earlier existence check.

Related errors


AI-assisted analysis of peass-ng/PEASS-ng@53fb989abc (2026-09-02). Data as JSON: /api/errors/6b83493b5b988f32. Report an issue: GitHub.