Feature Upgrade Issue: Deleted SPWebs : An error occurred while enumerating through a collection


Introduction

Recently I published a post about issues when upgrading Site Scope features in SharePoint. The issue was related to deleted Site Collections which were still in the recycle bin.

After resolving this issue I decided to do some testing with other deleted SharePoint objects. The next logical object type to delete was an SPWeb object.

Unfortunately further issues were found and the following section explains how they were found and the approach to resolve them.

 

How the Issue was Approached

The approach taken was the following:-

  • Build a Web Scoped Feature marked v1.0.0.0
  • Install the SharePoint Solution
  • Create a number of Webs and Activate the feature on those webs
  • Delete one of the Webs
  • Update the Web Scoped Feature to v2.0.0.0
  • Upgrade the SharePoint Solution to deploy the new version of the Web Scoped Feature
  • Use Install-SPFeature [FeatureName] –Force to upgrade the feature
  • Run a PowerShell command to execute the SPSite.QueryFeatures() function

The following PowerShell was run to query for Features that need to be upgraded.

 $site=Get-SPSite http://sharepoint; $site.QueryFeatures("Web", $true); 

The result of the script displayed the following:-

 $site.QueryFeatures("Web",$true);  An error occurred while enumerating through a collection: Unable to access web scoped feature (Id: f41cc668-37e5-4743-b4a8-74d1db3fd8a4) because it references  a non-existent or broken web (Id: 3bd828cf-b747-4111-b888-5953b0d9aaa3) on sit e 'http://dev.itsp.local'.  Exception: System.ArgumentException: Value does not  fall within the expected range.    at Microsoft.SharePoint.SPWebCollection.get_Item(Guid id)    at Microsoft.SharePoint.SPFeatureEnumeratorBase.GetCachedWeb(SPSite site, Gu id webId, Guid featureId). At line:1 char:20 + $site.QueryFeatures >> ("Web",$true)     + CategoryInfo          : InvalidOperation: (Microsoft.Share...esultCollec    tion:SPFeatureQueryResultCollection) [], RuntimeException     + FullyQualifiedErrorId : BadEnumeration 

 

Solution

The approach to solving this issue was not to write a workaround but to run a script which checks for deleted SPWeb objects in the site collection.

 $site = Get-SPSite http://sharepoint; $site.RecycleBin | ?{$_.ItemType -eq "Web"}; 

The script will display the SharePoint Web Objects that have been deleted and are still found in the site collections recycle bin.

The deleted SPWeb objects can be removed from the recycle bin using the following PowerShell command.

 $site = Get-SPSite http://sharepoint;  $deletedWebs = $site.RecycleBin | ?{$_.ItemType -eq "Web"}; $deletedWebs | % {$site.RecycleBin.Delete($_.Id)} 

This will delete the SPWeb objects from the recycle bin and the Feature Upgrade process can continue.

Please be careful when running this script! Only run it when you know that none of the SharePoint Web sites are not needed!

 

Anyway hope that helps!

Querying for Feature Upgrades error: The site with id cannot be found


Introduction

I am involved in a large project which is creating a large number of SharePoint webs. The webs content and configuration are being modified using Features and Feature Upgrades.

We are using PowerShell to process the Feature Upgrades using Chris O’Brien’s excellent SharePoint Feature Upgrade Kit.

One of the issues that we started to see during testing was when looking for Features which are scoped at the Site Collection using the SPWebApplication object’s QueryFeatures(SPFeatureScope, Boolean) function.

The following PowerShell was being used:-

$webapp = Get-SPWebApplication http://dev.itsp.local;
$webapp.QueryFeatures("Site",$true);

When this code was run in SharePoint 2010 Management Console the following error was displayed.

An error occurred while enumerating through a collection:
The site with the id f6f2e2bb-46bf-4c46-995e-65055512114e could not be found..
At line:1 char:22 + $webapp.QueryFeatures <<<< ("Site",$true); + CategoryInfo
: InvalidOperation: (Microsoft.Share...esultCollection:SPFeatureQueryResultCollection) [],
RuntimeException + FullyQualifiedErrorId : BadEnumeration

Investigation

Investigation started by looking at whether this error could be reproduced on other SharePoint environments which it could. Further testing was performed using different SharePoint builds including SharePoint 2010 Service Pack 1 and Cumulative Updates from June 2011 to December 2011.

The cause of the error seems to be when you have a site collection that has been deleted from SharePoint but had a feature that needs to be upgraded.

Looking in the Content Database for the Web Application revealed a entry in the AllSites table which looked like this:-

contentdb_deletedsiteentry

Reminder: Accessing the SharePoint databases is not supported by Microsoft and should not be performed in a production environment.

The row in the database has a column called Deleted which has a status of 1.

Using the Get-SPSite cmdlet the Site Collection could not be found. However, a colleague reminded me that there is a Get-SPDeletedSite. This returns back site collections that are found in the site collection recycle bin. The command returned a site collections that had been deleted a few weeks ago.

There is a function, Remove-SPDeletedSite but while this removes the site collection so it cannot be accessed via Get-SPDeletedSite, the error still occurs and the record is still found in the Content Database.

The issue seems to be down to the way that the SPWebApplication.QueryFeatures function works and does not filter the site collections which have been deleted and hence the error occurs.

Solution

Currently there is no fix for this issue that I am aware of. However, all is not lost and a workaround was possible by a few additional lines of PowerShell.

$webapp = Get-SPWebApplication http://dev.itsp.local;
$webapp.Sites | ForEach-Object {$queryFeatureResults += $_.QueryFeatures("Site",$true)};

This PowerShell command will enumerate through all the SPSite in the Web Application and call the same function but on each Site Collection. This gets around the problem with the QueryFeature() function finding the deleted site collection.

queryfeature-foreach-withresult