peass-ng/PEASS-ng · error · IOException

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

Error message

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

What it means

DeleteEmptySubdirectoriesCore throws IOException with message 'The target directory is a file, not a directory: [{0}]' when the fsEntryInfo resolved from the given path reports IsDirectory == false. DeleteEmptySubdirectories only makes sense on directories, so AlphaFS fails fast with this explicit message rather than letting the native layer return a generic error.

Source

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

         {
            if (pathFormat == PathFormat.RelativePath)
               Path.CheckSupportedPathFormat(path, true, true);

            if (!File.ExistsCore(transaction, true, path, pathFormat))
               NativeError.ThrowException(Win32Errors.ERROR_PATH_NOT_FOUND, path);

            fsEntryInfo = File.GetFileSystemEntryInfoCore(transaction, true, Path.GetExtendedLengthPathCore(transaction, path, pathFormat, GetFullPathOptions.TrimEnd | GetFullPathOptions.RemoveTrailingDirectorySeparator | GetFullPathOptions.FullCheck), false, pathFormat);

            if (null == fsEntryInfo)
               return;
         }

         #endregion // Setup


         // Ensure path is a directory.
         if (!fsEntryInfo.IsDirectory)
            throw new IOException(string.Format(CultureInfo.InvariantCulture, Resources.Target_Directory_Is_A_File, fsEntryInfo.LongFullPath));


         var dirs = new Stack<string>(1000);
         dirs.Push(fsEntryInfo.LongFullPath);

         while (dirs.Count > 0)
         {
            foreach (var fsei in EnumerateFileSystemEntryInfosCore<FileSystemEntryInfo>(true, transaction, dirs.Pop(), Path.WildcardStarMatchAll, null, DirectoryEnumerationOptions.ContinueOnException, null, PathFormat.LongFullPath))
            {
               // Ensure the directory is empty.
               if (IsEmptyCore(transaction, fsei.LongFullPath, pathFormat))
                  DeleteDirectoryCore(transaction, fsei, null, false, ignoreReadOnly, true, PathFormat.LongFullPath);

               else if (recursive)
                  dirs.Push(fsei.LongFullPath);
            }
         }
      }

View on GitHub (pinned to 53fb989abc)

Solutions

  1. Check Directory.Exists(path) and that it is not a file (File.Exists) before calling.
  2. Inspect FileSystemEntryInfo.IsDirectory via File.GetFileSystemEntryInfo before invoking.
  3. Filter your path list to directories only using Directory.GetFileSystemEntries / attributes.
  4. Catch IOException and log/skip non-directory entries in batch cleanup loops.

Example fix

// before
Directory.DeleteEmptySubdirectories(p); // p may be a file
// after
var info = File.GetFileSystemEntryInfo(p);
if (info != null && info.IsDirectory)
    Directory.DeleteEmptySubdirectories(p);
Defensive patterns

Strategy: validation

Validate before calling

var info = File.GetFileSystemEntryInfo(path);
if (info == null || !info.IsDirectory)
    throw new InvalidOperationException($"{path} is not a directory");

Type guard

bool IsDirectoryEntry(FileSystemEntryInfo e) => e != null && e.IsDirectory;

Try / catch

try { Directory.DeleteEmptySubdirectories(path); }
catch (IOException ex) when (ex.Message.Contains("is a file")) { logger.LogWarning("Skipping non-directory {Path}", path); }

Prevention

When it happens

Trigger: Calling Directory.DeleteEmptySubdirectories / DeleteEmptySubdirectoriesTransacted with a path that points to a regular file; a reparse point/symlink that resolves to a file; stale path captured before the directory was replaced by a file.

Common situations: Automated cleanup jobs iterating a list of paths where some entries are files; configuration/user input supplying a file path; a race where another process swapped the directory for a file between enumeration and the call.

Related errors


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