TLDR: Make sure site names start with a letter. This includes sites defined within configuration files, as well as FXM site definitions. If a FXM site is created and published to the web database then you will have to manually delete the item from the database before Sitecore will handle a request without throwing an exception. Sitecore says the issue is fixed in 8.2 update 5.
The site is down. It doesn’t matter which server you try, they all show the same error message: Expression must evaluate to a node-set. Logs don’t provide anything new, the site worked the night before, and no files have changed.
Looking at the stack trace we decide the SiteInfo.GetCacheSize() method is where we’ll start our search. Loading up the assembly in our decompiler we start figuring out what the code does.
The first thing we notice is that when Sitecore is attempting to get a cache size it will prefer to use the properties passed to it. For sites defined in patch files these are the attributes defined on the <site /> elements.
We do a quick sanity check and make sure our site definitions haven’t been modified and aren’t missing anything. Everything seems fine, but the stack trace indicates that we’re making it to the Factory.CreateObject() call. Taking a closer look reveals how the invalid XPath expression is being constructed: it includes the site name.
What does this mean for us? Any site name that starts with a number, and is missing cache size information in the properties collection, will cause Sitecore to be inaccessible. (Note: Sitecore Support says this is fixed in 8.2 update 5)
After a thorough search of config files we determine that we have no site definitions that would cause this problem. Turning back to the stack trace we see a call to DefaultSiteContextFactory.GetSites(). A quick look shows a call to the SiteManager.GetSites() method:
A little digging around in the SiteManager shows that, like most manager classes in Sitecore, they all delegate their logic to providers. It’s time to look back at our config files for any modifications to the <siteManager>.
We find that FXM is providing site definitions from items in the database, and that they don’t include any cache size information.
With Sitecore inaccessible you’ll have to manually find, and rename, or delete the offending site definition(s).
In order to find all the children of the “/sitecore/system/Marketing Control Panel/FXM” item you’ll have to use the following query:
select * from items where parentid = '40AC2D94-D9D5-4907-8B3A-346A9DC8BD35'
Once the issues are fixed your site will come back to life. Time to submit a support ticket. A little while later you hear back from Sitecore: this is a known bug, there’s no hotfix, but it’s fixed in 8.2 update 5, till then make sure your site names don’t start with a number.
The workaround is simple enough, but I worry about the content editors who may be unaware, or accidentally create a FXM site that can take down everything. Let’s try to make it a bit safer for them.Digging into the FxmSiteProvider we see that Sites are created by an instance of an IDomainMatcherSiteFactory, and that the FxmSiteProvider has a constructor to let us inject that dependency.
First we create a custom site factory (available on GitHub) which sets the cache size properties on the Site instance it returns.
Next we try to patch the FXM provider configuration but find that when Sitecore’s configuration factory tries to resolve the correct constructor to invoke that it does not play nicely with base types. Since the constructor accepts interfaces we cannot patch constructor parameters (if someone gets it work let me know).
Our next step is to subclass the FxmSiteProvider, override the constructors to pass in our custom site factory, and patch in our custom provider.
Now we can create our site:
And verify that Sitecore sees our site, including cache sizes, using the excellent PowerShell extensions by running the following at the PowerShell console:
Marketers and editors can now safely create FXM sites, even ones that start with numbers, without bringing Sitecore down.
Source code available on GitHub.