peass-ng/PEASS-ng · error · DirectoryNotEmptyException

ERROR_DIR_NOT_EMPTY

ERROR_DIR_NOT_EMPTY

Error message

({145}) The directory is not empty: [{pathLp}]

What it means

DeleteDirectoryNative throws DirectoryNotEmptyException (Win32 error 145, ERROR_DIR_NOT_EMPTY) when the native RemoveDirectory call fails because the directory still contains entries. This surfaces from Directory.Delete when recursive=false (or recursion failed to empty it), since non-recursive deletion only works on empty directories. It wraps the OS error with the offending path in the message.

Source

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

            // RemoveDirectory() / RemoveDirectoryTransacted()
            // 2014-09-09: MSDN confirms LongPath usage.

            // RemoveDirectory on a symbolic link will remove the link itself.

            ? NativeMethods.RemoveDirectory(pathLp)

            : 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);

View on GitHub (pinned to 53fb989abc)

Solutions

  1. Call Directory.Delete(path, true) with recursive:true to remove contents first.
  2. Enumerate and delete contents explicitly, then delete the now-empty directory.
  3. Retry after ensuring no other process is writing into the directory (close handles/stop services).
  4. Catch DirectoryNotEmptyException and decide per-path whether to force-delete or skip.

Example fix

// before
Directory.Delete(tempDir); // fails: not empty
// after
Directory.Delete(tempDir, true); // recursive delete
Defensive patterns

Strategy: try-catch

Validate before calling

if (Directory.EnumerateFileSystemEntries(path).Any())
    Directory.Delete(path, true); // recursive for non-empty
else
    Directory.Delete(path, false);

Try / catch

try { Directory.Delete(path, false); }
catch (DirectoryNotEmptyException) { Directory.Delete(path, true); }

Prevention

When it happens

Trigger: Calling Directory.Delete(path) or Delete(path, recursive:false) on a directory containing files/subdirectories; DeleteDirectoryCore invoked from DeleteEmptySubdirectoriesCore or junction teardown on a folder that gained new entries between emptiness checks and deletion; hidden/system files present that made the folder appear empty.

Common situations: Deleting a temp/cache folder that an application is still writing to; race condition where another process created a file after the caller verified the directory was empty; passing recursive:false by default overload while assuming recursive behavior like Directory.Delete(path, true).

Related errors


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