We found a bug in the Release Candidate version of Team Foundation Server which I shall ‘report’ here.   We accidentally found ourselves in the position of having a team build containing two Visual Studio solutions and a project that was included in both solutions.   It appears that TFS Build cannot perform builds in this situation.   When it gets to the compilation build step for the ‘shared’ project, if aborts abnormally.   The error in the Windows event log reports a SOAP fault caused by a SQL 512 error which indicates that a SQL sub-select is returning multiple rows in a situation where only one row is permissible.  The error message is:


“Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.”


Looking at the event log on the TFS server, I can see that the error occurs on line 46 of the sp_InsertProjectDetails stored procedure, and occurs when TFS Build invokes the http://<tfsserver>/Build/v1.0/BuildStore.asmx web service.   Unfortunately, stored procedures are encrypted in the TFSBuild database, so I can’t investigate this further.


It looks like TFS Build analyses all the solutions within a build and records each solution and project file it finds in The FileDirectory table.   The ProjectDetails table contains a ProjectFileId column containing the ID of a solution or project file, and also a ParentProjectFileId column, both of which act as foreign keys for entries in FileDirectory.   For my build, this table records the Project File Id of the ‘shared’ project against two different Parent Project File Ids, corresponding to the two solutions.   It looks like sp_InsertProjectDetails selects data from the ProjectDetails table within a sub-select, and makes an unjustified assumption that each ProjectFileId appears just once within this table.


The workaround was, of course, very simple.   Ensure that each project appears in just on solution per team build.   What a pity Microsoft’s test scripts for TFS Build were not written to test for this scenario.