I spent this afternoon working on a custom VirtualPathProvider for two websites we have at work. We need to share resources(master pages, themes, scripts, etc) between the two and I figured embedding resources in a separate project would be the best bet. The VirtualPathProvider implementation takes any old path its given(like "/resources/style.css") and looks to see if there's an embedded resource that matches. This worked out great after I got around some annoying implementation details(MSDN documentation on VirtualPathProvider is kind of terrible).
Then I got stumped. On some pages everything would work as expected. The page would include all the referenced embedded resources and load without a hitch. On other pages, though, the same reference would result in an "Directory not found" HttpException for no apparent reason. After tearing my hair out trying to find something wrong with my VirtualPathProvider, I went to look at the full stacktrace of what was wrong. I probably should have done that in the first place seeing as my problem wasn't specifically being thrown by my VirtualPathProvider class.
[HttpException (0x80070003): Directory 'C:\Solutions\Website\Resources\Dir' does not exist. Failed to start monitoring file changes.]
System.Web.FileChangesMonitor.FindDirectoryMonitor(String dir, Boolean addIfNotFound, Boolean throwOnError)
System.Web.FileChangesMonitor.StartMonitoringPath(String alias, FileChangeEventHandler callback, FileAttributesData& fad)
System.Web.Caching.CacheDependency.Init(Boolean isPublic, String filenamesArg, String cachekeysArg, CacheDependency dependency, DateTime utcStart)
System.Web.Script.Services.WebServiceData.GetWebServiceData(HttpContext context, String virtualPath, Boolean failIfNoData, Boolean pageMethods, Boolean inlineScript)
System.Web.Script.Services.PageClientProxyGenerator.GetClientProxyScript(HttpContext context, IPage page, Boolean debug)
System.Web.UI.ScriptManager.OnPagePreRenderComplete(Object sender, EventArgs e)
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
What's ScriptManager doing? Beats me, but I looked into it and came across this: HttpException when serving a page with a ScriptManager using a Virtual Path Provider
It turns out that, prior to ASP 4.0, the ScriptManager control has a bug that causes it to ignore any custom VirtualPathProvider classes whenever it does whatever it does internally. This only happens when the ScriptManager's EnablePageModes property is set to true. Setting this to false immediately fixed my problem. That may not solve everyone's problem, though. There's a hotfix available for this specific issue, though I can't vouch for it.