Fix “List cannot be deleted while on hold or retention policy” Error on SharePoint Online
Problem: When trying to delete a document library in SharePoint Online, it gave an error message: “list cannot be deleted while on hold or retention policy.”
Solution:
As the error message says: List cannot be deleted while on hold or retention policy. This error is due to the site being under hold or retention policy. So, to delete the list, you must delete all its files and subfolders first. Otherwise, you should remove the retention policy under Office 365 compliance center. You can quickly check if the site is under hold by going to:
- Admin centers >> Security & Compliance >> Search & investigation
- Click on eDiscovery, and check if you have created any cases >> If you see any cases, click Open
- Under Hold, check if you see any sites. Â
Deleting files in each folder could be haunting, especially with a deep folder structure. Fortunately, we have PowerShell to relieve the burden.
PowerShell to Clear Document Library’s Content and then Delete
This PowerShell script deletes all files, sub-folders, and the given document library in SharePoint Online.
#Load SharePoint CSOM Assemblies
Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.dll"
Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.Runtime.dll"
#Variables
$SiteURL = "https://crescent.sharepoint.com/Sites/Marketing"
$LibraryName = "Branding Templates"
#Function to Delete all files and Sub-folders of a given Folder
Function Empty-SPOFolder([Microsoft.SharePoint.Client.Folder]$Folder)
{
Try {
#Get All Files from the Folder
$Files = $Folder.Files
$Ctx.Load($Files)
$Ctx.ExecuteQuery()
#Iterate through each File in the folder
Foreach($File in $Files)
{
#Delete the file
$Folder.Files.GetByUrl($File.ServerRelativeUrl).Recycle() | Out-Null
Write-host -f Green "Deleted File '$($File.Name)' from '$($File.ServerRelativeURL)'"
}
$Ctx.ExecuteQuery()
#Process all Sub Folders of the given folder
$SubFolders = $Folder.Folders
$Ctx.Load($SubFolders)
$Ctx.ExecuteQuery()
Foreach($Folder in $SubFolders)
{
#Exclude "Forms" and Hidden folders
If( ($Folder.Name -ne "Forms") -and (-Not($Folder.Name.StartsWith("_"))))
{
#Call the function recursively to empty the folder
Empty-SPOFolder -Folder $Folder
#Delete the folder
$Ctx.Web.GetFolderById($Folder.UniqueId).Recycle() | Out-Null
$Ctx.ExecuteQuery()
Write-host -f Green "Deleted Folder:"$Folder.ServerRelativeUrl
}
}
}
Catch {
write-host -f Red "Error:" $_.Exception.Message
}
}
Try {
#Get Credentials to connect
$Cred= Get-Credential
#Setup the context
$Ctx = New-Object Microsoft.SharePoint.Client.ClientContext($SiteURL)
$Ctx.Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($Cred.Username, $Cred.Password)
#Get the Library
$Library = $Ctx.web.Lists.GetByTitle($LibraryName)
$RootFolder = $Library.RootFolder
$Ctx.Load($Library)
$Ctx.Load($RootFolder)
$Ctx.executeQuery()
#Call the function to empty Folder
Empty-SPOFolder $RootFolder
#Delete the Document Library
$Library.Recycle() | Out-Null
$Ctx.ExecuteQuery()
Write-host -f Green "Deleted Document Library Successfully!"
}
Catch {
write-host -f Red "Error:" $_.Exception.Message
}
Delete Document Library in Retention Hold using PnP PowerShell
Let’s fix the “list cannot be deleted while on hold or retention policy” error on SharePoint Online by deleting all files and folders first and then the document library using PnP PowerShell. Please note, if a file is checked out, you can’t delete it! It must be checked in to be able to delete. PowerShell to Bulk Check In All Documents in SharePoint Online
#Parameters
$SiteURL = "https://crescent.sharepoint.com/sites/Marketing"
$ListName = "Branding Templates"
#Connect to the Site
Connect-PnPOnline -URL $SiteURL -Credentials (Get-Credential)
#Get the web & document Library
$Web = Get-PnPWeb
$List = Get-PnPList -Identity $ListName
#Function to delete all Files and sub-folders from a Folder
Function Empty-PnPFolder([Microsoft.SharePoint.Client.Folder]$Folder)
{
#Get the site relative path of the Folder
If($Folder.Context.web.ServerRelativeURL -eq "/")
{
$FolderSiteRelativeURL = $Folder.ServerRelativeUrl
}
Else
{
$FolderSiteRelativeURL = $Folder.ServerRelativeUrl.Replace($Folder.Context.web.ServerRelativeURL,[string]::Empty)
}
#Get All files in the folder
$Files = Get-PnPFolderItem -FolderSiteRelativeUrl $FolderSiteRelativeURL -ItemType File
#Delete all files in the Folder
ForEach ($File in $Files)
{
#Delete File
Remove-PnPFile -ServerRelativeUrl $File.ServerRelativeURL -Force -Recycle
Write-Host -f Green ("Deleted File: '{0}' at '{1}'" -f $File.Name, $File.ServerRelativeURL)
}
#Process all Sub-Folders
$SubFolders = Get-PnPFolderItem -FolderSiteRelativeUrl $FolderSiteRelativeURL -ItemType Folder
Foreach($SubFolder in $SubFolders)
{
#Exclude "Forms" and Hidden folders
If( ($SubFolder.Name -ne "Forms") -and (-Not($SubFolder.Name.StartsWith("_"))))
{
#Call the function recursively
Empty-PnPFolder -Folder $SubFolder
#Delete the folder
$ParentFolderURL = $FolderSiteRelativeURL.TrimStart("/")
Remove-PnPFolder -Name $SubFolder.Name -Folder $ParentFolderURL -Force -Recycle
Write-Host -f Green ("Deleted Folder: '{0}' at '{1}'" -f $SubFolder.Name, $SubFolder.ServerRelativeURL)
}
}
}
#Get the Root Folder of the Document Library and call the function to empty folder contents recursively
Empty-PnPFolder -Folder $List.RootFolder
#Now delete the document library
Remove-PnPList -Identity $ListName -Recycle -Force
Write-host -f Green "Document Library Deleted Successfully!"
If you just want to clear the document library without deleting the library, comment line#50 – Remove-PnPList. Here is another post on deleting all files and folders from a document library: SharePoint Online: How to Delete All Files in a Document Library using PowerShell?
PnP PowerShell to Empty a SharePoint Online Document Library
The above script just works fine with smaller libraries of < 5000 files. But on larger libraries, it gets “Get-PnPFolderItem : The attempted operation is prohibited because it exceeds the list view threshold.” error, as the Get-PnPFolderItem can’t handle large lists and libraries. So, here is the alternate script to empty a document library by deleting all files and folders in it faster with the PnP Batch method:
#Parameters
$SiteURL = "https://crescent.sharepoint.com/sites/Inventory"
$ListName = "Branding Templates"
Try {
#Connect to PnP Online
Connect-PnPOnline -Url $SiteURL -Interactive
$List = Get-PnPList $ListName
$ItemCount = $List.ItemCount
If($ItemCount -eq 0) { Write-host "Document Library is Already Empty!" -f Yellow; Break}
#Get All Items from the Library
$global:counter = 0
$ListItems = Get-PnPListItem -List $ListName -PageSize 500 -Fields ID -ScriptBlock { Param($items) $global:counter += $items.Count; Write-Progress -PercentComplete `
($global:Counter / $ItemCount * 100) -Activity "Getting Items from List" -Status "Getting Items $global:Counter of $($ItemCount)"}
Write-Progress -Activity "Completed Getting Items from Library $($List.Title)" -Completed
#Sort List Items based on Server Relative URL - Descending
$SortedItems = $ListItems | Select-Object @{Name="ServerRelativeURL";Expression={$_.FieldValues.FileRef}}, ID | Sort-Object -Descending -Property ServerRelativeURL
#Delete List Items in the Batch
$Batch = New-PnPBatch
ForEach ($Item in $SortedItems)
{
Remove-PnPListItem -List $ListName -Identity $Item.ID -Recycle -Batch $Batch
#Write-host "Deleted Item:"$Item.ServerRelativeURL
}
Invoke-PnPBatch -Batch $Batch -Details
Write-host -f Green "All Items in the Library deleted Successfully!"
}
Catch {
write-host "Error: $($_.Exception.Message)" -foregroundcolor Red
}
Thanks for your script. I want to delete files and folders older that 60 days. Can you please help? This is for SharePoint Online site using pnp shell.
Here you go: SharePoint Online: Delete All Files Older than 30 Days in a Document Library using PowerShell