How to deal with “Missing server side dependencies” error
In this post I am going to show my methodology for dealing with the "Missing server side dependencies" error. I do not have a good way to deal with it online but one good way to deal with it on-premises.
For this example I am using the SharePoint 2010, but the problem is the same in the newest versions (though honestly I did not check it on the SharePoint 2016).
This error appears in the SharePoint Health Analyzer
and looks like this:
Let us think for a second - why does this error happen and what is the inner reason for it?
Let us say your server side solution has some artefact. In this case it is the web part. Once upon a time the web part was a part of the solution and was deployed somewhere. Then you have decided you do not need the web part or simply has renamed it. However the content database already contains an information like "page xxx has a web part yyy in this zone with this settings".
And if the webpart does not exist the database is inconsistent.
It is not necessary a web part. You can add a ghosted module file and then decided to rename it. So the SharePoint will keep the information about the file in the database but the file will not be there.
Could be also that the web part gallery (_catalogs/wp contains information about your webpart and the webpart is also part of farm solution and do not exist anymore)
So the first step is to find where the web part is.
The way I was always doing it is via SQL. With the SQL you can search through the content database and find that specific string.
I have been making and losing the script the number of times, most recent time I have found a script in here
And I have slightly modified it so it not only shows the table where the string is stored, but also specific lines.
--
use WSS_Content -- could be your database name here
DECLARE
@search_string VARCHAR(100),
@table_name SYSNAME,
@table_schema SYSNAME,
@column_name SYSNAME,
@sql_string VARCHAR(2000)
SET @search_string = 'yourwebpart.webpart'
DECLARE tables_cur CURSOR FOR SELECT TABLE_SCHEMA, TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE'
OPEN tables_cur
FETCH NEXT FROM tables_cur INTO @table_schema, @table_name
WHILE (@@FETCH_STATUS = 0)
BEGIN
DECLARE columns_cur CURSOR FOR SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = @table_schema AND TABLE_NAME = @table_name AND COLLATION_NAME IS NOT NULL -- Only strings have this and they always have it
OPEN columns_cur
FETCH NEXT FROM columns_cur INTO @column_name
WHILE (@@FETCH_STATUS = 0)
BEGIN
-- SET @sql_string = 'IF EXISTS (SELECT * FROM ' + QUOTENAME(@table_schema) + '.' + QUOTENAME(@table_name) + ' WHERE ' + QUOTENAME(@column_name) + ' LIKE ''%' + @search_string + '%'') PRINT ''' + QUOTENAME(@table_schema) + '.' + QUOTENAME(@table_name) + ', ' + QUOTENAME(@column_name) + ''''
SET @sql_string = 'IF EXISTS (SELECT * FROM ' + QUOTENAME(@table_schema) + '.' + QUOTENAME(@table_name) + ' WHERE ' + QUOTENAME(@column_name) + ' LIKE ''%' + @search_string + '%'') SELECT * FROM ' + QUOTENAME(@table_schema) + '.' + QUOTENAME(@table_name) + ' WHERE ' + QUOTENAME(@column_name) + ' LIKE ''%' + @search_string + '%'''
EXECUTE(@sql_string)
FETCH NEXT FROM columns_cur INTO @column_name
END
CLOSE columns_cur
DEALLOCATE columns_cur
FETCH NEXT FROM tables_cur INTO @table_schema, @table_name
END
CLOSE tables_cur
DEALLOCATE tables_cur
--
Once I have run the script I have seen this:
So now I know that the site with ID 089D94D0-7BF4-4A51-9E29-2BACABC30DF4 contains a missing web part in the gallery, I guess I could just delete it? A simple get-spsite PowerShell command could find me the site and the gallery.
Here is another example of another webpart. This time we can see it happens on 2 different web sites - a default site and a personal site of the administrator.
However, running this script is not enough. This is another good script that will find your webpart on all pages.
SELECT Webs.FullUrl, Webs.Title, AllDocs.DirName, AllDocs.LeafName, AllWebParts.tp_DisplayName, AllWebParts.tp_ID
FROM AllDocs, Sites, AllWebParts, Webs
WHERE Webs.Id = Sites.RootWebId AND AllDocs.Id = AllWebParts.tp_PageUrlID
AND Sites.Id = AllDocs.SiteId AND tp_WebPartTypeId IN (
SELECT DISTINCT tp_WebPartTypeId FROM AllWebParts (NOLOCK)
WHERE tp_WebPartTypeId IS NOT NULL AND tp_Assembly IS NULL AND tp_Class IS NULL)
-- if you add this line, the script will find your specific web part instead of giving you all web parts on all pages
--AND (AllWebParts.tp_DisplayName = 'yourwebpartname')
Results of the script when run with my webpart:
Pic4.
Now depending on the number of pages and problems you could either clean the pages manually or make a script that will go through the pages and delete the webpart from it.
One more hint to finish this. Recently I met a problem I could not solve easily. Some users had added the obsolete Web Part to the Personal View of the page. So the script that would clean the web part could not delete this or even find the users! The content database did not help in this case.
So the simplest way to remove all personalized settings and the faulty/missing webpart from the page is to add the ?contents=1 to the page URL. This will bring the page into maintenance mode.
Here is how you remove all personal users settings
And here is how you delete the problematic web part from the page