Sunday, April 10, 2011

Fixing TFS 2010 builds that are failing with “The specified path, file name, or both are too long”

I’ve been setting up automated builds for some SharePoint 2010 projects, and getting this “The specified path, file name, or both are too long” error way too often for my taste – it looks something like this in the build log:

C:\Builds\3\Client XYZ-Intranet\Rolling\Sources\My Long Project Name\My Long Project Name\Features\Webparts\Webparts.feature: 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.

You can run into the problem on non-SharePoint projects, but SharePoint projects tend to have the problem worse, because they go a little crazy with directory nesting…  Here’s an example from my local machine of a path generated during the build process:

C:\projects\XYZ\trunk\ Client.XYZ.SharePoint.Webparts\Client.XYZ.SharePoint.Webparts\pkg\Debug\ Client.XYZ.SharePoint.Webparts\ Client.XYZ.SharePoint.XYZHome.Webparts_Webparts\ VirtualProductManager\VirtualProductManager.webpart

That was 224 characters, and only 22 of it was my local path.    The code base builds on my machine, but not on the server – it’s local path is 47 characters (C:\Builds\3\Client XYZ-Intranet\Rolling\Sources), so if I could trim 25 off of it, I’d probably be ok.  The problem is, all of that is in $(SourceDir) (where my project build starts from), so I can’t touch it for the build, or can I?…  Luckily, I have full rights on the build server, so I’m going to use some stuff I found on to take a hatchet to this.

First stop: Build agent configuration

In the “Team Foundation Server Administration Console” on the build server, I went to the properties for my build agent:



That dialog defines the "Working directory” for the build agent, defaulting to “$(SystemDrive)\Builds\$(BuildAgentId)\$(BuildDefinitionPath)”.  Based on the above link, I’m going to go with “$(SystemDrive)\B\$(BuildDefinitionId)” – that should take the '”uilds” off the base directory, the TFS project name (19 characters), a backslash, and the build name (7 characters) out, and replace them with just a 32-bit number (which should be at most 10 digits, but since it starts from 1, it’s much more likely to be 3-4 digits), saving me 23 characters minimum, almost to my magic number.  The above thread made mention of changing the “SourcesSubDirectory” app setting in “TfsBuildService.exe.config” to shorten the “Sources” part of the path, but with TFS 2010, that file doesn’t exist anymore, so I’ll have to try to shorten it another way.

Second stop: build definition

I may not have been able to shorten $(SourceDir), but it’s just “$(BuildDir)\Sources”, right?  I can just configure the build to pull the code to “$(BuildDir)\S” instead of “$(SourceDir)”, and I should save another 6 characters, getting me to 29 characters saved, which should be enough.


Well, does it work?

Yes.  Even better than I thought.  My code now starts at “C:\B\9\S” (8 characters) on the build server instead of “C:\Builds\3\Client XYZ-Intranet\Rolling\Sources” (47 characters), saving me 39 characters and letting my build run.  Now to figure out why my tests are failing…