The Feature That Did Not Want To Go

Trying to deploy a solution with either Visual Studio or PowerShell we have all seen error messages like this:

Error occurred in deployment step 'Add Solution': A feature with ID <GUID> has already been installed in this farm. Use the force attribute to explicitly re-install the feature.

and this:

Add-SPSolution : The solution cannot be deployed. Directory "My.Soulution_Feature" associated with feature '<GUID1>' in the solution is used by feature '<GUID2>' installed in the farm. All features must have unique directories to avoid overwriting files.

Obviously, something got out of sync …

The first error may be solved by this Install-SPSolution -Identity my.solution.wsp -Force

But this will not always work. To cut a long story short: in this case I ended up deleting the site collection – no problem as this was a virtual machine used for development and we have scripted setups.

Just remember that beginning with SharePoint 2010 SP1 deleted sites and site collections go to a recycle bin. Only after deleting them there you will be able to deploy your solution again. There is no UI for that, use the Get-SPDeletedSite and Remove-SPDeletedSite commandlets.

As I was interested in finding less invasive methods to fix errors like these in production environments, I started to dig a bit deeper …

The Feature that was long gone

Checking the usual hideaways for features using the UI showed that it wasn’t activated on the site collection and wasn’t even deployed in the farm. There also was no respective feature folder.

Using Notepad++‘s “Find in files” I found GUID2 in an old copy of the project – trying to deploy that failed with switched GUIDs.

Of course any use of Disable-SPFeature or Uninstall-SPFeature resulted in an error message. The stsadm variants reported success but didn’t do anything.

Where did SharePoint think this feature was installed? Get-SPFeature should tell:

[DBG]: PS C:\Users\Administrator\Documents> Get-SPFeature –Limit ALL | Where-Object {$_.DisplayName -like "My*"}


DisplayName                    Id                                       CompatibilityLevel   Scope                         
-----------                    --                                       ------------------   -----                         
My.Soulution1_Feature1         56d59638-f916-480e-8d8e-396b1b89dab3     15                   Farm                          
My.Soulution2_Feature1         b75a018b-c755-41a8-9446-dea1d45e7037     15                                                 
My.Soulution3_Feature1         ca750767-2951-4a3d-9ace-125c25146790     15                   Site                          

So, SharePoint thought it was installed but the missing Scope value showed there was something terribly wrong. Nothing new, unfortunately.

Next I tried Feature Admin for SharePoint 2013. While it was straight forward to use and very informative, it couldn’t get rid of the feature:

FeatureError_InFA_marked

After that I tried the trusty SharePoint Manager 2013. It listed the feature definition in the farm’s features and allowed me to delete it but that didn’t seem to have any effect.

Finally I took a look with SQL Server Management Studio at the content database. Of course I had no intent to change anything directly in the database – never ever do that!

As expected a query like this (note GUID’s characters in upper case) returned an empty result:

SELECT * 
FROM [WSS_Content_LocalTeamSite].[dbo].[Features]
WHERE FeatureId = 'B75A018B-C755-41A8-9446-DEA1D45E7037'

OK, time for some shortcutting. I knew the feature contained a web part. Which sites are using it?

SELECT tp_SiteId, tp_WebPartIdProperty 
FROM [WSS_Content_LocalTeamSite].[dbo].[AllWebParts]
WHERE tp_Assembly LIKE 'My%'

tp_SiteId                              tp_WebPartIdProperty
8F9F6B31-149B-4B5A-9594-1083C146DC90   g_5a587fc0_0ad3_4122_a7ee_245afa3f832b
8F9F6B31-149B-4B5A-9594-1083C146DC90   g_a11649e4_3093_401a_aaf8_f61436344fa2
8F9F6B31-149B-4B5A-9594-1083C146DC90   NULL
8F9F6B31-149B-4B5A-9594-1083C146DC90   g_a11649e4_3093_401a_aaf8_f61436344fa2

Don’t worry – this is the result of developing a script to put that web part on a page. As I knew anyway which site and page it was I skipped getting it’s URL from tp_SiteId and just looked at the page’s source code:

<div class="ms-rtestate-read ms-rte-wpbox" contenteditable="false">
   <div class="ms-rtestate-notify  ms-rtestate-read 861d0c9d-eda9-4fea-8549-dd442726eefe" id="div_861d0c9d-eda9-4fea-8549-dd442726eefe">
   </div> 
   <div class="ms-rtestate-read" id="vid_861d0c9d-eda9-4fea-8549-dd442726eefe" style="display: none;">
   </div> 
</div>
<div class="ms-rtestate-read ms-rte-wpbox" contenteditable="false" unselectable="on">
   <div class="ms-rtestate-notify  ms-rtestate-read a11649e4-3093-401a-aaf8-f61436344fa2" id="div_a11649e4-3093-401a-aaf8-f61436344fa2" unselectable="on">
   </div>
   <div id="vid_a11649e4-3093-401a-aaf8-f61436344fa2" unselectable="on" style="display: none;">
   </div>
</div>
<div class="ms-rtestate-read ms-rte-wpbox" contenteditable="false">
   <div class="ms-rtestate-notify  ms-rtestate-read 5a587fc0-0ad3-4122-a7ee-245afa3f832b" id="div_5a587fc0-0ad3-4122-a7ee-245afa3f832b" unselectable="on">
   </div>
   <div id="vid_5a587fc0-0ad3-4122-a7ee-245afa3f832b" unselectable="on" style="display: none;">
   </div>
</div> 
<div class="ms-rtestate-read ms-rte-wpbox" contenteditable="false">
   <div class="ms-rtestate-notify  ms-rtestate-read eb68dc2a-059e-4be0-b2d0-582106489539" id="div_eb68dc2a-059e-4be0-b2d0-582106489539">
   </div> 
   <div class="ms-rtestate-read" id="vid_eb68dc2a-059e-4be0-b2d0-582106489539" style="display: none;">
   </div> 
</div> 

Yes, that matches quite nicely (note GUIDs using “_” vs. “-“). Now let’s call it a moral victory and just delete the site collection :-).

Fun fact: even after deleting the site collection from the recycle bin and successfully deploying the solution querying [WSS_Content_LocalTeamSite].[dbo].[AllWebParts] returned the old results.

External References

Advertisements
This entry was posted in Uncategorized and tagged , , . Bookmark the permalink.

4 Responses to The Feature That Did Not Want To Go

  1. surya says:

    Follow below steps.
    1. Exclude the feature which is creating the error.
    2. deploy it.
    3. include the feature.
    4. Then deploy it.
    Bingo. It worked for me.

  2. Moband Bua says:

    Not only should you never directly modify the content database, you should never directly query it either. Not even a SELECT because you can cause conflicts with the transactional locking.,,

  3. Simon says:

    Using the command “Get-SPFeature -Limit ALL | Where-Object {$_.Scope -eq $null}” I was able to select the problematic features I was able to call .Delete() on the features, and deploy my solution.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s