The Specified Directory Service Attribute Or Value Does Not Exist

Getting an exception “The specified directory service attribute or value does not exist”, when you try to search a user in an AD container using System.DirectoryServices.AccountManagement.UserPrincipal::FindByIdentity

This happens because if there is no container specified, the principal context class will create a System.DirectoryServices.DirectoryEntry object by binding to builtin CN=Users container to start searching for users. System.DirectoryServices is built on top of ADSI. ADSI by default does an objectclass=* search as part of its normal bind process unless the fastbind flag is specified. If the user performing the search does not have permission to read the attributes of default users contain, the search operation will fail, thus causing “The specified directory service attribute or value does not exist”, exception.

This is also true when searching computer objects using ComputerPrincipal::FindByIdentity and you don’t have read permission on CN=Computer container and have not specified a container in the constructor of System.DirectoryServices.AccountManagemnt.PrincipalContext. The blog explains the rules followed by the PrincipalContext class in selecting a container when one has not been explicitly specified in the constructor.


Resolution: The right approach is to specify the container where the object resides if it is known the name of the container. Alternatively, is it possible to simply specify the domain naming context as the container. The performance in this case will be inferior to specifying the name of the container explicitly, since the search will encompass the entire domain.

The issue can be reproduced by using the following code (change the name of the domain and searched user to values appropriate for the needed environment):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.DirectoryServices.AccountManagement;
using System.DirectoryServices;
namespace TestInvalidCreds
{

class Program

{

static void Main(string[] args)

{

PrincipalContext pc = new PrincipalContext(ContextType.Domain, "dc163608.local");

UserPrincipal up = UserPrincipal.FindByIdentity(pc, IdentityType.SamAccountName, "InnerUser");

}

}

}

  1. Modify the code as below (change the name of the domain and searched user to values appropriate for the needed environment).


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.DirectoryServices.AccountManagement;
using System.DirectoryServices;
namespace TestInvalidCreds

{

class Program

{

static void Main(string[] args)

{

PrincipalContext pc = new PrincipalContext(ContextType.Domain, "dc163608.local","dc=dc163608,dc=Local");

UserPrincipal up = UserPrincipal.FindByIdentity(pc, IdentityType.SamAccountName, "InnerUser");

}

}

}

  1. It should now return the object.