“Unhandled exception” is not something that makes people happy. If this exception suddenly appears and crashes your beautiful Sitecore site, first you probably feel surprise, then fear and finally panic. If you are reading this article, I assume you are done with the first part and now want to know how to fix it.
Let’s have a closer look at the issue. This is how the error looks:
There are multiple reasons why this error can happen but the most probable for Sitecore projects is StackOverflowException.
StackOverflowException is different from all other exception types. MSDN states that:
Starting with the .NET Framework 2.0, you can’t catch a StackOverflowException object with a try/catch block, and the corresponding process is terminated by default.
This the reason why that exception crashes the IIS w3wp.exe process and the whole site (and other sites if they share the same App Pool) goes down. Of course, if you are lucky, you will find the cause of the issue by just checking logs as I did. Unfortunately, luck is something that rarely happens and only with the best:). It is more likely to see very little or no information about this error in log files.
This happens because the code that writes exception details into the log is stored in try/catch block. That code is not executed for StackOverflowException which means that the error will be logged only if it is detected before the exception is thrown.
So, if there is nothing in the logs, what can you do? There is a solution. It is called a Memory Dump.
Collecting the Memory Dump
It is all about timing. A memory dump should be collected at the moment when StackOverflowException is thrown but the application is not released yet (i.e., the moment you see the error dialog on your screen). You can collect it by using Windows Task Manager. Open it, go to the Details tab, find the w3wp.exe process by process ID and run the “Create dump file” command with a right mouse click. The file you will get as a result of these steps is a full memory dump for the process.
If you do not see the dialog and cannot easily reproduce the error, there is still a way to collect the memory dump. You will need to set up a tool that will listen to the process and automatically collect it as soon as an exception thrown again. There are number of tools that can do that. I personally like Microsoft Debug Diagnostic Tool. It is easy to install and configure. Check this article for details how to capture StackOverflowException.
By the way, if you are collecting the dump file in a remote environment, do not forget to compress it before downloading. The zipped archive will be ~90% smaller.
Analyzing the Memory Dump
Now, when you have your file, you need to analyze it. I prefer Microsoft Debug Diagnostic Tool for doing that. That is one of hidden gem every .NET developer should know about. It may be not as powerful as WinDbg but it is much easier to use.
To analyze your data dump, run the DebugDiag 2 Analysis app, pick the CrachHangAnalysis Rule, add your dump file as shown below and start the analysis.
In a few seconds you will get your report. There are a lot of interesting things you can find in it and you can explore them later.
What you need to do now is scroll down until you see “Previous .NET Exceptions Report”:
Click on the Thread ID and voilà… This is the information you have been looking for.
For example, this is what I found in my stack:
... Sitecore.Data.Managers.ItemManager.GetItem(Sitecore.Data.ID, Sitecore.Globalization.Language, Sitecore.Data.Version, Sitecore.Data.Database)+d9 Sitecore.Data.TemplateRecords.GetTemplate(Sitecore.Data.ID, Sitecore.Globalization.Language)+c8 Sitecore.Data.Items.TemplateItem.get_BaseTemplates()+a7 Sitecore.PathAnalyzer.Extensions.ItemExtensions.GetAllBaseTemplates(System.Collections.Generic.List<code>1, Sitecore.Data.Items.TemplateItem, Boolean)+2b Sitecore.PathAnalyzer.Extensions.ItemExtensions.GetAllBaseTemplates(System.Collections.Generic.List</code>1, Sitecore.Data.Items.TemplateItem, Boolean)+51 and many more repetitions of last line
And this is the line of code that opened my eyes and gave me a clue as to what actually happened.
As you can see, in my case the issue was related to template inheritance. Template parents can be edited by anybody who has access and it happened that some content editor created circular references.
And for comparison, this is what I found in my logs:
4220 15:32:10 ERROR Circular template inheritance detected in 'Advanced' 4220 15:32:10 ERROR This may be caused by explicitly assigned base id's or by the setting 'DefaultBaseTemplate' in web.config. 4220 15:32:10 ERROR Template trail: System/Templates/Sections/Advanced : System/Templates/Standard template : Products/Secondary Categories : Products/Secondary Categories : Products/Secondary Categories : Products/Secondary Categories : Products/Secondary Categories : Products/Secondary Categories : Products/Secondary Categories : Products/Secondary Categories : Products/Secondary Categories : Products/Secondary Categories : Products/Secondary Categories : Products/Secondary Categories : Products/Secondary Categories : Products/Secondary Categories : Products/Secondary Categories
You can see the template name here which gives you enough information to open Content Editor and fix the issue.
Great job, Sitecore!