I've been working with a client on an integration between their current requirements management system in Caliber and TFS. We recently started receiving the TF20507 error after upgrading to TFS2015. Our integration work used the TFS API, and it would go after User data in TFS as it was trying to insert records. The User Retrieval logic started throwing the TF20507, but the error doesn't tell you which user, and it doesn't tell you which field in the user record is causing the issue. It only tells you the invalid character (U+0009, or a TAB character in this case).
Doing some searching around the interwebs for that error message returned some example code and methods for tracking down the error user.. my trouble was that the code examples I was running across were all using the TFS API for TFS 2010, and the methods they were using were not working with the newer TFS API's.
So I ended up working through the code and converting things over in a manner that would give me the SID of the user that was causing the issue, only now in a TFS API that works with newer versions. I ended up with the code below, which will loop through all of the users in the Project Collection Valid Users group, and it tries to call the IIdentityManagementService.ReadIdentities method for each SID. This lets me find which user SID throws the TF20507 error.
var GSS = tfs.GetService<IIdentityManagementService>();
TeamFoundationIdentity SIDS =
GSS.ReadIdentity(
Microsoft.TeamFoundation.Framework.Common.IdentitySearchFactor.General,
"Project Collection Valid
Users",
Microsoft.TeamFoundation.Framework.Common.MembershipQuery.Expanded,
Microsoft.TeamFoundation.Framework.Common.ReadIdentityOptions.None);
foreach(var member in SIDS.Members)
{
if (member.IdentityType == "System.Security.Principal.WindowsIdentity")
{
string v =
member.GetType().ToString();
string[] mIDS = {
member.Identifier };
try {
TeamFoundationIdentity[][] u =
GSS.ReadIdentities(IdentitySearchFactor.Identifier,
mIDS, MembershipQuery.Expanded, ReadIdentityOptions.ExtendedProperties);
// Console.WriteLine(u[0][0].UniqueName);
}
catch(System.Exception ex)
{
Console.WriteLine("Error :
" +
ex.GetBaseException().Message);
Console.WriteLine("for sid :" +
member.Identifier);
}
}
}
This code ends up spitting out the TF20507 Error and the SID for each User that is throwing the exception/causing my troubles.
That's great and all, but knowing the SID is only half the battle.. I then needed to find which User ID's were the culprits... for that we took a peek in to the TFS Config database to find the SIDs (NOTE -- We are only SELECTING data here to find the culprit.. DON'T try to edit data in the TFS Configuration database! It won't end well for you unless you REALLY REALLY know what you're doing...)
SELECT *
FROM [Tfs_Configuration].[dbo].[tbl_Identity]
WHERE Sid = 'put in your SID here'
Once we found the user ID's of the user's causing the trouble, we were able to remove them from TFS. Working with the security folks who manage the Active Directory, we found that the user's had TAB characters in a description field in Active Directory. Having the Active Directory accounts updated to remove all the TAB's we then re-added the users to TFS... and no more issue!