Failed to create a custom control 'PublishingSiteActionsMenuCustomizer'
January 15, 2014
A very weird and hard to pinpoint SharePoint error has haunted me these last days.
The Symptoms
You have a SharePoint site collection that uses Publishing features. Suddenly, the users can't access your site. All user accounts, including site collection administrators, get the dreaded "Access Denied" error. In my case, it was SharePoint 2010 with a custom site template with publishing features included in it.
The SharePoint log files mention this:
Failed to create a custom control 'PublishingSiteActionsMenuCustomizer', feature 'Publishing' (id:22a9ef51-737b-4ff2-9346-694633fe4416) using attributes (ControlSrc='', ControlAssembly='Microsoft.SharePoint.Publishing, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c', ControlClass='Microsoft.SharePoint.Publishing.WebControls.PublishingSiteActionsMenuCustomizer':
The Cause
It is really strange that SharePoint can't load it's own components. But, the real cause it that the web application that a culprit site collection is running on is missing its "superuser" settings. The SuperUsers are the users configured for Publishing infrastructure to read and write publishing cache. It seems that if the users are not correctly configured, the publishing infrastructure fails badly and SharePoint interprets it as "Access Denied".
Two blog posts were of great help: Khashish Sukhija and Nico Marten's. Thank you guys! I checked the web application properties from PowerShell and the super user entries were empty for the web application that was behaving strangely.
The Fix
Execute the script found on Nico's post (reproduced here for convenience, all credit is his) and IISRESET.
\# This script will add the superuser and superreader account to the Policy for web app
\# and also set the web application properties so that the users will be used for caching
\# The script is designed in a way that you do NOT have to adjust the script before useAdd-PSSnapin Microsoft.SharePoint.PowerShell
\# Function
function addUsersToPolicyAndProperties
{
$webapps = get-spwebapplication
$superuser = Read-Host "Fill in the SuperUser account: <Domain><Username>"
$superreader = Read-Host "Fill in the SuperReader: <Domain><Username>"
#foreach statement that will loop through all web applications
foreach($webapp in $webapps)
{
try {
$SUpolicy = $webapp.Policies.Add($superuser,$superuser)
$SUpolicy.PolicyRoleBindings.Add($webapp.PolicyRoles.GetSpecialRole(\[Microsoft.SharePoint.Administration.SPPolicyRoleType\]::FullControl))
$SRpolicy = $webapp.Policies.Add($superreader,$superreader)
$SRpolicy.PolicyRoleBindings.Add($webapp.PolicyRoles.GetSpecialRole(\[Microsoft.SharePoint.Administration.SPPolicyRoleType\]::FullRead))
$webapp.Properties\["portalsuperuseraccount"\] = \[string\]$superuser
$webapp.Properties\["portalsuperreaderaccount"\] = \[string\]$superreader
$webapp.Update()
Write-Host "$webapp.displayname has been configured correctly"
}
catch
{
Write-Host "Error adding the users for $webapp.displayname" -fore red
}
}
Write-Host "All web applications are done, press any key to exit" -fore green
$x = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
}
#Call function
addUsersToPolicyAndProperties