Skip to content

Remove-Item throws The directory is not empty when deleting large file trees #27710

Description

@Tadas

Prerequisites

Steps to reproduce

> 1..100 | % { New-Item -Type Directory -Force "C:\Temp\repro\$_\$(1..100 -join '\')" | Out-Null }
> Remove-Item "C:\Temp\repro" -Recurse -Force

Expected behavior

`C:\Temp\repro` is removed

Actual behavior

Remove-Item: The directory is not empty. : 'C:\Temp\repro\1\1\2\3\4\5\6'.
Remove-Item: The directory is not empty. : 'C:\Temp\repro\1\1\2\3\4\5'.
Remove-Item: The directory is not empty. : 'C:\Temp\repro\1\1\2\3\4'.
Remove-Item: The directory is not empty. : 'C:\Temp\repro\1\1\2\3'.
Remove-Item: The directory is not empty. : 'C:\Temp\repro\1\1\2'.
Remove-Item: The directory is not empty. : 'C:\Temp\repro\1\1'.
Remove-Item: The directory is not empty. : 'C:\Temp\repro\1'.
Remove-Item: The directory is not empty. : 'C:\Temp\repro\10\1\2\3\4\5\6\7\8\9\10\11\12\13\14\15\16\17\18\19\20\21\22\23\24\25\26\27\28\29\30\31\32\33\34\35\36\37\38\39\40\41\42\43\44\45\46\47\48\49\50\51\52\53\54\55\56\57\58\59\60\61'.
... and etc.

Error details

> get-error

Exception             :
    Type       : System.IO.IOException
    TargetSite :
        Name          : RemoveDirectoryInternal
        DeclaringType : [System.IO.FileSystem]
        MemberType    : Method
        Module        : System.Private.CoreLib.dll
    Message    : The directory is not empty. : 'C:\Temp\repro'.
    Source     : System.Private.CoreLib
    HResult    : -2147024751
    StackTrace :
   at System.IO.FileSystem.RemoveDirectoryInternal(String fullPath, Boolean topLevel, Boolean allowDirectoryNotEmpty)
   at System.IO.DirectoryInfo.Delete()
   at Microsoft.PowerShell.Commands.FileSystemProvider.RemoveFileSystemItem(FileSystemInfo fileSystemInfo, Boolean force)
TargetObject          : C:\Temp\repro
CategoryInfo          : WriteError: (C:\Temp\repro:DirectoryInfo) [Remove-Item], IOException
FullyQualifiedErrorId : RemoveFileSystemItemIOError,Microsoft.PowerShell.Commands.RemoveItemCommand
ErrorDetails          :
InvocationInfo        :
    MyCommand        : Remove-Item
    ScriptLineNumber : 1
    OffsetInLine     : 1
    HistoryId        : 36
    Line             : Remove-Item "C:\Temp\repro" -Recurse -Force -ProgressAction Continue
    Statement        : Remove-Item "C:\Temp\repro" -Recurse -Force -ProgressAction Continue
    PositionMessage  : At line:1 char:1
                       + Remove-Item "C:\Temp\repro" -Recurse -Force -ProgressAction Continue
                       + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    InvocationName   : Remove-Item
    CommandOrigin    : Internal
ScriptStackTrace      : at <ScriptBlock>, <No file>: line 1
PipelineIterationInfo :
      0
      1

Environment data

Name                           Value
----                           -----
PSVersion                      7.6.2
PSEdition                      Core
GitCommitId                    7.6.2
OS                             Microsoft Windows 10.0.17763
Platform                       Win32NT
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0…}
PSRemotingProtocolVersion      2.4
SerializationVersion           1.1.0.1
WSManStackVersion              3.0

Remove-Item "C:\Temp\repro" -Recurse -Force -ProgressAction SilentlyContinue does not help, only $ProgressPreference = 'SilentlyContinue' works.

Guess this is somewhat dependant on the storage performance / load on the box, manged to repro it only on some machines.

Process Monitor shows GetTotalFiles worker thread scanning the file tree while the pipeline thread tries to SetDispositionInformationFile Delete: True but gets back NOT EMPTY

Metadata

Metadata

Assignees

No one assigned

    Labels

    Needs-TriageThe issue is new and needs to be triaged by a work group.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions