65535 files is one too many

Back in March I was working with Visual Studio, developing an ASP.NET MVC project, and everything was going fine until one day I tried to load the solution I was working on, and when loading one specific project I started seeing an error.

---------------------------
Microsoft Visual Studio
---------------------------
Failed to create extension manager for the target platform 'Microsoft.Data.Tools.Schema.Sql.SqlAzureDatabaseSchemaProvider'.
---------------------------
OK
---------------------------

Just given the error, it leads one to believe that the problem has to do with SQL or Azure or Databases, or anything similar. I googled around, and couldn’t find any kind of resolution. Most advice said to re-install various components of Visual Studio like the Azure SDK which I tried multiple times to no avail. Another bit of advice was to delete the *.suo files, and try re-cloning the repository. Deleting the *.suo files didn’t help but when re-cloning the repository I started having even more problems because suddenly SourceTree was bugging out and crashing for me too (remember this fact, it becomes relevant later in the article)! At this point I knew something had to be up, something really bizarre – I dug deeper.

One of the error messages I had seen when trying to re-load the project that was failing was

An exception has been encountered. This may be caused by an extension. You can get more information by examining the file (...)\AppData\Roaming\Microsoft\VisualStudio\12.0\ActivityLog.xml

I looked into the log file and found the following stack trace corresponding to the issue I was having:

<entry>
 <record>1194</record>
 <time>2015/03/06 21:32:39.394</time>
 <type>Error</type>
 <source>Editor or Editor Extension</source>
 <description>System.IO.IOException: The file exists.&#x000D;&#x000A;&#x000D;&#x000A; at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)&#x000D;&#x000A; at System.IO.__Error.WinIOError()&#x000D;&#x000A; at System.IO.Path.InternalGetTempFileName(Boolean checkHost)&#x000D;&#x000A; at Microsoft.VisualStudio.Text.Utilities.WpfHelper.LoadCursorDPIAware(Stream cursorStream)&#x000D;&#x000A; at Microsoft.VisualStudio.Text.Editor.Implementation.LeftSelectionMargin.get_RightArrowCursor()&#x000D;&#x000A; at Microsoft.VisualStudio.Text.Editor.Implementation.LeftSelectionMarginProvider.CreateMargin(IWpfTextViewHost textViewHost, IWpfTextViewMargin containerMargin)&#x000D;&#x000A; at Microsoft.VisualStudio.Text.Utilities.ContainerMargin.&lt;AddMargins&gt;b__2(IWpfTextViewMarginProvider mp)&#x000D;&#x000A; at Microsoft.VisualStudio.Text.Utilities.GuardedOperations.InstantiateExtension[TExtension,TMetadata,TExtensionInstance](Object errorSource, Lazy`2 provider, Func`2 getter)</description>
 </entry>

Upon an initial glance this doesn’t look very helpful. Given how much of closed black-box Visual Studio is, we don’t gain too much insight from this. I resorted to going line by line and trying to piece together what was happening just based on the function names. What ended up piquing my interest was that the top of the stack, the most recent call, was coming from the System namespace when it was trying to get a temporary file name. “The file exists” was an odd error to see, because when I was loading up the project I can’t imagine it would be trying to overwrite any file. I searched around for the GetTempFileName function which is what System.IO.Path.InternalGetTempFileName actually maps to (e.g. it just passes it through to the Windows API) – you can confirm this by viewing the source on GitHub (hooray for .NET Core CLR being open sourced!)

16-bits

Let me back up a bit before I get to the solution. I rarely delete my history, and I rarely clean up my temporary files or even reboot my machine for that matter. I am of the *nix mentality that one should really only ever have to ideally reboot their machine if you’ve installed a new kernel or something. I also like having a nice history an archive of everything I do. In today’s world, a terabyte is a disposable, trivial amount of space so there’s really no need to have to clear temporary files. You see where I’m going with this?

As it turns out, there is a “well known” (seriously? in 2015 this is a problem?) limitation of GetTempFileName which is that it cannot create more than 65535 (216 – 1, for those who really should familiarize themselves better with powers of two) files. Once your temporary files reaches that number, it will fail to create a new temporary file/provide you a name for one. I opened my temporary folder (Go to windows explorer and type %TEMP% in the address bar, then hit enter) and sure enough the status bar said “<some number greater than 65535> files” and my suspicions were confirmed. After running disk cleanup, wiping that folder, everything went back to daisies and rainbows. I confirmed that SourceTree was also suffering from the same problem, and it had been resolved after this fix as well.

The moral of the story is don’t have arbitrary limits on how many times your function will work, and if you must, then at least have a descriptive error message.

Big thank you to the stackoverflow thread that in the end led me to the answer, provided here for your reference: StackOverflow: VS2013 crashing when I go to Team Explorer and click on ‘Changes’

0 Comments

Leave a Reply

Your email address will not be published.