ASP.NET compiler error caused by node_modules

Update: I have revisited this issue, because Visual Studio still uses an old version of npm and installs the modules in a nested structure. You can edit the version of npm Visual Studio uses or run the npm install commands yourself to prevent this issue.

Problem

Recently our build server (AppVeyor) encountered an error while compiling our application.

ASPRUNTIME: The specified path, file name, or both are too long. The fully qualified file name must be less than 260 characters, and the directory name must be less than 248 characters.

Initially I was confused, because the build had succeeded locally, so I began researching to determine what had happened. First I googled the error to see if any of the top search results were similar circumstances. Luckily for me John Reilly had blogged about the issue and that also made me remember previously reading about node module nesting causing issues. We have some node modules installed and it seemed a possible culprit. I updated my local modules and when I rebuilt the project I encountered the error too, confirming the node modules as the cause.

Attempted Solution

My first thoughts on how to resolve the error was to configure the ASP.NET compiler to ignore the node_modules directory. The node_modules directory is not required as part of the ASP.NET compile process (for us at least), so it seemed sensible that the compiler should ignore it. Unfortunately I did some research and I could discover a possible way of doing this.

Solution

After trying to have the compiler ignore the node_modules directory, I decided to upgrade to npm version 3. I knew that version 3 featured a flatter dependencies structure, which would fix the problem of long file paths being caused by nested dependencies. Be aware that upgrading npm on Windows involves some manual configuration, see here. After I upgraded and reinstalled the modules the build was succeeding again locally.

Configuring the build server to use npm 3 was fairly straight forward. The build server was already scripted to call “npm install”, I simply had to update the script to install npm 3 beforehand. The install script ended up becoming as follows.

Solution Analysis

Upgrading npm resolved the build error, but it didn’t really resolve the problem. Even though we specify the versions of the modules we depend on those modules can have their own dependencies and may not specify the exact version they depend on. This potential variance in builds is undesirable. It may result in errors such as this scenario initially occurring on the build server or worse, the build could be successful with some subtle variance in the results produced.

I happened to discus this scenario with Joshua Wulf and he mentioned that he’d heard a talk that recommended that all node modules be committed into your project’s source control. I haven’t done any further research on this yet, but I think this is something we will have to take up. The build process be repeatable (i.e. the same output should be produced every time the same commit is built) and using npm to fetch the node modules breaks this.

Additional Research

I actually did some additional investigation, in between discovering the node modules were causing the build error and resolving the error. I wanted to know why the ASP.NET compiler was even looking at the node_modules directories. First I enabled diagnostic logging of MSBuild as shown in the following screenshot.

diagnostic msbuild

With the additional diagnostic data I could see that the error occurred in the MvcBuildViews target. The diagnostic data also gave me the aspnet_compiler.exe command that was being run. I took this command and ran it manually adding the “-errorstack” option to it as well. This gave me the following stack trace.

error ASPRUNTIME: The specified path, file name, or both are too long. The fully qualified file name must be less than 260 characters, and the directory name must be less than 248 characters.

[PathTooLongException]: The specified path, file name, or both are too long. The fully qualified file name must be less than 260 characters, and the directory name must be less than 248 characters.
at System.IO.PathHelper.GetFullPathName()
at System.IO.Path.NormalizePath(String path, Boolean fullCheck, Int32 maxPathLength, Boolean expandShortPaths)
at System.IO.Path.GetFullPathInternal(String path)
at System.Web.Hosting.MapPathBasedVirtualPathEnumerator..ctor(VirtualPath virtualPath, RequestedEntryType requestedEntryType)
at System.Web.Hosting.MapPathBasedVirtualPathCollection.System.Collections.IEnumerable.GetEnumerator()
at System.Web.Compilation.BuildManager.PrecompileWebDirectoriesRecursive(VirtualDirectory vdir, Boolean topLevel)

at System.Web.Compilation.BuildManager.PrecompileWebDirectoriesRecursive(VirtualDirectory vdir, Boolean topLevel)
at System.Web.Compilation.BuildManager.PrecompileAppInternal(VirtualPath startingVirtualDir, IEnumerable`1 excludedVirtualPaths)
at System.Web.Compilation.BuildManager.PrecompileApp(VirtualPath startingVirtualDir, IEnumerable`1 excludedVirtualPaths)
at System.Web.Compilation.BuildManager.PrecompileApp(ClientBuildManagerCallback callback, IEnumerable`1 excludedVirtualPaths)
at System.Web.Compilation.BuildManagerHost.PrecompileApp(ClientBuildManagerCallback callback, List`1 excludedVirtualPaths)
at System.Web.Compilation.BuildManagerHost.PrecompileApp(ClientBuildManagerCallback callback, List`1 excludedVirtualPaths)
at System.Web.Compilation.ClientBuildManager.PrecompileApplication(ClientBuildManagerCallback callback, Boolean forceCleanBuild)
at System.Web.Compilation.ClientBuildManager.PrecompileApplication(ClientBuildManagerCallback callback)
at System.Web.Compilation.Precompiler.Main(String[] args)

I’ve cut out a several levels of recursive calls to the BuildManager PrecompileWebDirectoriesRecursive method. From the stack trace I started to look at the source code for some of the classes and methods on referencesource, but I decided I was getting sidetracked by my curiosity and start working on solving the error before I could understand why the ASP.NET compiler looks at the node_modules directory. If anyone knows what the compile was doing, I’d be interested to know.

Advertisements
ASP.NET compiler error caused by node_modules

3 thoughts on “ASP.NET compiler error caused by node_modules

    1. Thanks for the suggestion. I’m not sure how that program can prevent this error, unless it is able to change how Windows works.
      I think the best solution is to use the latest version of npm, which Node.js is now distributed with. This installs dependencies in a Windows friendly way (among other improvements).

      Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s