When an application, appliance or script can't bind to Active Directory, the LDAP client usually reports a short result code (49, 8, 81…) and, for error 49, a hex data value buried in the server message. That data value is the real reason. This quick reference decodes the error 49 data codes, the other LDAP results domain controllers return, and the signing, channel binding and LDAPS failures that show up after hardening, each with the usual cause and the first thing to check.
Codes in this quick reference
AcceptSecurityContext error, data 525: user not found (ERROR_NO_SUCH_USER)LDAP client / ldp.exeAcceptSecurityContext error, data 52e: user name or password is incorrect (ERROR_LOGON_FAILURE)LDAP client / ldp.exeAcceptSecurityContext error, data 530: logon hours restriction (ERROR_INVALID_LOGON_HOURS)LDAP client / ldp.exeAcceptSecurityContext error, data 531: not allowed to sign in from this computer (ERROR_INVALID_WORKSTATION)LDAP client / ldp.exeAcceptSecurityContext error, data 532: password expired (ERROR_PASSWORD_EXPIRED)LDAP client / ldp.exeAcceptSecurityContext error, data 533: account disabled (ERROR_ACCOUNT_DISABLED)LDAP client / ldp.exeAcceptSecurityContext error, data 568: too many security IDs in the token (ERROR_TOO_MANY_CONTEXT_IDS)LDAP client / ldp.exeAcceptSecurityContext error, data 701: account expired (ERROR_ACCOUNT_EXPIRED)LDAP client / ldp.exe
+ 16 more codes in the tables below.
How to read these codes#
A failed bind in ldp.exe looks like this. The DSID and the trailing v… value change between builds; ignore them.
Error <49>: ldap_bind_s() failed: Invalid Credentials.
Server error: 8009030C: LdapErr: DSID-0C0906F9, comment: AcceptSecurityContext error, data 52e, v4f7c
Error 0x8009030C The logon attempt failed- The LDAP result code (
49) is the category: invalid credentials. Java, Linux and appliance logs wrap the same server string in their own message, so search their logs forAcceptSecurityContext. - The data value (
52e) is a Win32 error code in hex: 0x52E is 1326,ERROR_LOGON_FAILURE. Decode any value on a Windows machine withcertutil -error 0x52eornet helpmsg 1326. - ADSI, .NET and PowerShell surface the same failure as an HRESULT that ends in the Win32 code, for example
0x8007052E. - The domain controller's side of an authentication failure is in its Security log (events 4625, 4771 and 4776). Decode those with the logon failure codes reference and the Kerberos error codes reference.
Error 49: AcceptSecurityContext data codes#
| Data | Meaning | Usual cause | First check |
|---|---|---|---|
data 525 | User not found (ERROR_NO_SUCH_USER, 1317). | The bind name matches no account: a typo, a DN that changed after an OU move, or an account in another domain. | Find the account by UPN and bind with its UPN or full DN. |
data 52e | User name or password is incorrect (ERROR_LOGON_FAILURE, 1326). | The password was changed or rotated but the app still stores the old one, or the app's config mangles special characters. | Bind with the same credentials in ldp.exe from the app server, then look for the account's failure events on the DC. |
data 530 | Logon hours restriction (ERROR_INVALID_LOGON_HOURS, 1328). | The account's logon hours exclude the current time. | Account › Logon Hours in the user's properties. |
data 531 | Not allowed to sign in from this computer (ERROR_INVALID_WORKSTATION, 1329). | The Log On To list doesn't include the computer the request comes from. | Account › Log On To (userWorkstations). |
data 532 | Password expired (ERROR_PASSWORD_EXPIRED, 1330). | A service account under the normal domain password policy. | Set a new password; consider a fine-grained password policy or a managed service account if the app supports one. |
data 533 | Account disabled (ERROR_ACCOUNT_DISABLED, 1331). | Disabled by a clean-up job or offboarding. | The Enabled flag; who disabled it (event 4725 on the DCs). |
data 568 | Too many security IDs in the token (ERROR_TOO_MANY_CONTEXT_IDS, 1384). | The account belongs to too many groups, nested ones included. | Count the token groups (command below) and trim memberships. |
data 701 | Account expired (ERROR_ACCOUNT_EXPIRED, 1793). | The account's expiry date has passed. | AccountExpirationDate on the account. |
data 773 | Password must be changed (ERROR_PASSWORD_MUST_CHANGE, 1907). | User must change password at next logon is set, typically after an admin reset. | Clear the flag or set the password the app will use. |
data 775 | Account locked out (ERROR_ACCOUNT_LOCKED_OUT, 1909). | Bad-password attempts hit the lockout threshold, often the app itself retrying an old password. | Unlock, then trace the source of the bad attempts before the app locks it again. |
# Account state behind most data codes (badPwdCount isn't replicated, so ask the PDC emulator)
$pdc = (Get-ADDomain).PDCEmulator
Get-ADUser svc-ldap -Server $pdc -Properties Enabled, LockedOut, badPwdCount, PasswordExpired, PasswordLastSet, AccountExpirationDate |
Select-Object Enabled, LockedOut, badPwdCount, PasswordExpired, PasswordLastSet, AccountExpirationDate
# Data 568: how many group SIDs end up in the token
(Get-ADUser svc-ldap -Properties tokenGroups).tokenGroups.CountOther LDAP result codes from domain controllers#
| Code | Meaning | Usual cause | First check |
|---|---|---|---|
8 LDAP_STRONG_AUTH_REQUIRED | The DC requires signing for this bind. | A simple bind on port 389 without TLS, or a SASL bind without signing, against a DC set to require signing. | Move the app to LDAPS or StartTLS, or to a signed SASL bind (next section). |
19 LDAP_CONSTRAINT_VIOLATION | A value breaks a directory rule. | Usually a password write that fails the length, complexity or history rules; the extended error then carries 0000052D (ERROR_PASSWORD_RESTRICTION). | The policy that applies: Get-ADUserResultantPasswordPolicy (no output means the default domain policy: Get-ADDefaultDomainPasswordPolicy). |
32 LDAP_NO_SUCH_OBJECT | The object or search base doesn't exist. | Wrong base DN in the app, or the object was moved or deleted. | Confirm the DN with Get-ADObject. |
34 LDAP_INVALID_DN_SYNTAX | The distinguished name is malformed. | Typos or unescaped special characters (commas, plus signs) in a name. | Copy the value from the object's distinguishedName. |
49 LDAP_INVALID_CREDENTIALS | Authentication failed. | See the data codes above. | Read the data value. |
50 LDAP_INSUFFICIENT_RIGHTS | Bound, but not allowed to do this. | The account can't read or write the object or attribute; delegation is missing. | Permissions on the OU or object (dsacls). |
53 LDAP_UNWILLING_TO_PERFORM | The DC refuses the operation. | A password write over an unencrypted connection, or a directory rule; a domain join over quota logs 0000216D: SvcErr: DSID-031A124C, problem 5003 (WILL_NOT_PERFORM), data 0. | The extended error string that follows the code. |
68 LDAP_ALREADY_EXISTS | The object already exists. | Provisioning creates a name that's already taken. | Search for the name and sAMAccountName. |
81 LDAP_SERVER_DOWN | Can't contact the LDAP server. | Wrong host name, blocked port, DC down, or a failed TLS handshake on 636. | Test-NetConnection to 389 and 636; nltest /dsgetdc: for the domain. |
85 LDAP_TIMEOUT | The search timed out. | An expensive filter, a slow link or a busy DC. | Narrow the base and filter; test against a nearer DC. |
4 LDAP_SIZELIMIT_EXCEEDED | More results than one response returns. | The app doesn't request paged results. | Turn on paging in the app's LDAP settings. |
Through ADSI (PowerShell [adsi], .NET DirectoryEntry) the same results arrive as HRESULTs: 0x8007052E for LDAP_INVALID_CREDENTIALS, 0x8007203A for LDAP_SERVER_DOWN ("Cannot contact the LDAP server"), 0x80072030 for LDAP_NO_SUCH_OBJECT, 0x80072035 for LDAP_UNWILLING_TO_PERFORM, 0x80070005 for LDAP_INSUFFICIENT_RIGHTS and 0x80071392 for LDAP_ALREADY_EXISTS.
Signing, channel binding and LDAPS failures#
Strong Authentication Required (LDAP 8)#
Once Domain controller: LDAP server signing requirements is set to Require signing (registry LDAPServerIntegrity = 2 under HKLM\SYSTEM\CurrentControlSet\Services\NTDS\Parameters; 1 means None), clear-text simple binds and unsigned SASL binds fail. Microsoft's own test is a simple bind on port 389 in ldp.exe; on a hardened DC it returns:
ldap_simple_bind_s() failed: Strong Authentication RequiredFix the client, not the DC: point it at LDAPS (636, or 3269 for the global catalog), use StartTLS, or use a SASL bind that requests signing. Windows clients follow Network security: LDAP client signing requirements. To find every client still binding insecurely before you enforce, use the DC's LDAP interface events 2887 and 2889, covered in the AD DS, Netlogon and DNS events reference.
Channel binding#
Domain controller: LDAP server channel binding token requirements maps to LdapEnforceChannelBinding in the same registry key: 0 Never, 1 When Supported, 2 Always. Channel binding applies to SASL binds (NTLM, Negotiate, Kerberos) over TLS. It doesn't apply to simple binds over TLS, certificate binds or SASL sessions without TLS. With Always, an older client or library that does a SASL bind over LDAPS without a channel binding token fails as an authentication error even with the right password. Test When Supported first, find and update the clients that fail, then move to Always.
LDAPS (636) fails while 389 works#
The DC needs a certificate in its Local Computer › Personal store with the Server Authentication enhanced key usage, the DC's FQDN in the subject or subject alternative name, an accessible private key, and a chain the client trusts. Without one, the TLS handshake fails and ldp.exe and most libraries report error 81, which looks like a network fault. Connecting by IP address or by an alias that isn't in the certificate fails the name check on the client.
# On the DC: candidate LDAPS certificates
Get-ChildItem Cert:\LocalMachine\My |
Where-Object { $_.EnhancedKeyUsageList.FriendlyName -contains 'Server Authentication' } |
Select-Object Subject, DnsNameList, NotAfter, HasPrivateKey
# From the app server: is the port even open?
Test-NetConnection dc01.contoso.com -Port 636Test a bind the way the app does#
Reproduce the failure from the app server with the same account, port and bind type, and print the result code plus the server message:
Add-Type -AssemblyName System.DirectoryServices.Protocols
$id = New-Object System.DirectoryServices.Protocols.LdapDirectoryIdentifier('dc01.contoso.com', 636)
$conn = New-Object System.DirectoryServices.Protocols.LdapConnection($id)
$conn.SessionOptions.SecureSocketLayer = $true # $false for port 389
$conn.AuthType = [System.DirectoryServices.Protocols.AuthType]::Basic
$cred = Get-Credential # e.g. svc-ldap@contoso.com
try { $conn.Bind($cred.GetNetworkCredential()); 'Bind OK' }
catch { $e = $_.Exception.GetBaseException(); "{0} {1}" -f $e.ErrorCode, $e.ServerErrorMessage }A wrong password prints 49 followed by the AcceptSecurityContext … data 52e string; a TLS or network problem prints 81 with no server message.
How to verify a fix#
- Run the same bind test from the app server: you want
Bind OK, or an authenticated session inldp.exe. - Check the account on the PDC emulator:
badPwdCountback to 0 after a successful bind,LockedOutFalse, no new 4625 or 4771 events for it. - For signing work, the DC's daily summary of insecure binds should stop counting the app; for LDAPS, the app should connect with certificate validation turned on, not with checks disabled.
- Restart the app or its connector service and watch one full sync or login cycle, because many apps cache a failed connection.
Tip: A domain join that fails with LDAP 53 and 0x216d is a machine account quota or join-rights problem, not an LDAP one. See the domain join errors reference.

