Keycloak LDAP integration fails silently with generic error messages. The admin console shows “Connection refused” or “Test authentication failed” without revealing the actual cause. This guide catalogs every Keycloak LDAP error with exact log messages, Active Directory sub-codes, and fix commands.

For initial LDAP setup instructions, see Keycloak User Federation with LDAP and Active Directory.

Quick Diagnostic: Which Error Are You Seeing?

Admin Console / Log MessageJump To
Connection refusedConnection Errors
LDAP: error code 49Bind / Authentication Errors
SSLHandshakeException: PKIX path building failedTLS / SSL Errors
Test Connection passes, Test Authentication failsTLS / SSL Errors
PartialResultException: ReferralSearch and Sync Errors
SizeLimitExceededExceptionSearch and Sync Errors
Sync shows 0 imported, 0 updatedSearch and Sync Errors
LDAP: error code 53 - WILL_NOT_PERFORMPassword Change Errors
Groups sync but clicking a group raises errorsGroup Mapper Errors

Connection Errors

Connection Refused

j[aRvoaoxt.neaxmcienpgt.iCoonmmiusnijcaavtai.onneEtx.cCeopntnieocnt:Exlcdeappt.ieoxna:mpCloen.nceocmt:i3o8n9refused]

Causes (in order of likelihood):

  1. LDAP server is down — Verify the LDAP service is running
  2. Wrong port — LDAP uses 389, LDAPS uses 636, AD Global Catalog uses 3268/3269
  3. Firewall blocking — Check network path from Keycloak to LDAP server
  4. Wrong protocol/port combinationldaps:// on port 389 or ldap:// on port 636

Debug commands:

# Test TCP connectivity to LDAP port
nc -zv ad.example.com 389
nc -zv ad.example.com 636

# From inside a Keycloak Docker container
docker exec -it keycloak-container bash -c "curl -v telnet://ad.example.com:636"

# DNS resolution check
nslookup ad.example.com

Port Confusion Reference

PortProtocolConnection URL PrefixNotes
389LDAP (plaintext) or StartTLSldap://Never use plaintext in production
636LDAPS (TLS from start)ldaps://Requires CA cert in truststore
3268AD Global Catalogldap://Read-only, limited attributes
3269AD Global Catalog over SSLldaps://Read-only, limited attributes, encrypted

Common mistake: Using ldaps://ad.example.com:389 (LDAPS protocol on plaintext port) or ldap://ad.example.com:636 (plaintext protocol on LDAPS port). These combinations will always fail.

LDAP Connection Has Been Closed

javax.naming.CommunicationException:LDAPconnectionhasbeenclosed

This happens when the LDAP server closes idle connections, typically during high-load sync operations. Causes include connection pool exhaustion, LDAP server timeout, or network interruption.

Fix: Increase connectionPoolingMaxSize in Keycloak LDAP provider settings and check the LDAP server’s max connections configuration.

Bind and Authentication Errors

Error Code 49 — Invalid Credentials

javax.naming.AuthenticationException:[LDAP:errorcode49-InvalidCredentials]

Error code 49 is the generic “authentication failed” code, but Active Directory includes a hex sub-code that reveals the exact cause:

AD Sub-CodeMeaningFix
data 525User not foundVerify bind DN exists in AD
data 52eWrong passwordCorrect the bind credential
data 530Logon not permitted at this timeCheck AD time-of-day restrictions
data 531Logon not permitted from this workstationCheck AD workstation restrictions
data 532Password expiredReset the service account password
data 533Account disabledRe-enable the account in AD
data 701Account expiredExtend the account expiration date
data 773User must reset passwordReset password and clear “must change” flag

How to read the sub-code: Look for the full error in Keycloak server logs:

[LcDoAmPm:enetr:roArccceopdteSe4c9ur-it8y0C0o9n0t3e0x8t:eLrdraoprE,rrd:atDaSI5D2-e0,C0v940546339],

The data 52e part is the sub-code — this means “wrong password”.

Test your bind credentials before configuring Keycloak:

# Active Directory (full DN format)
ldapsearch -x -H ldaps://ad.example.com:636 \
  -D "CN=keycloak-svc,CN=Users,DC=corp,DC=example,DC=com" \
  -W \
  -b "DC=corp,DC=example,DC=com" \
  "(sAMAccountName=testuser)"

# Active Directory (UPN format — simpler)
ldapsearch -x -H ldaps://ad.example.com:636 \
  -D "[email protected]" \
  -W \
  -b "DC=corp,DC=example,DC=com" \
  "(sAMAccountName=testuser)"

# OpenLDAP
ldapsearch -x -H ldaps://ldap.example.com:636 \
  -D "cn=admin,dc=example,dc=com" \
  -W \
  -b "ou=people,dc=example,dc=com" \
  "(uid=testuser)"

Wrong Bind DN Format

The most common cause of error code 49 is using the wrong bind DN format:

#B#B#B#B#B#BiiiiiiWnWnCnAnCnCnRdRdOdLdOdOdOORSRRNDNDRDODRDRDGNGNENNENEN::C:C:C:C:TOTTkcCRkcujefoNReniuyor=Ey=dscrpFkCcOaF=tlw/ueTlpdraoaklyoemedtarelcaniemhkdylkLnIie-cDoU-D,PnsslNaPsAdA,uvlokNvPccscaaf-c=neskosf@e=rh-rvocxunscroasanvA,mrmemoccCapprettNt.lsai=ee,tvU(x,ciesAadnoeDmc=nDrp=aisolccr,neoceDl.mocCycut=)onocmtrosyr,pd,cD=Ce=xeaxmapmlpel,ed,cD=Cc=ocmom

Account Lockout Warning

Clicking Test Authentication in Keycloak admin console with wrong credentials counts as a failed login attempt in Active Directory. Repeated clicks can trigger the AD account lockout policy and lock out your bind service account.

Prevention: Always test credentials with ldapsearch on the command line before configuring Keycloak.

TLS and SSL Errors

PKIX Path Building Failed (Most Common TLS Error)

jSauvnaCxe.rntePta.tshsBlu.iSlSdLeHraEnxdcsehpatkieoEnx:ceupntaibolne:tPoKIfXinpdatvhalbiudilcdeirntgiffiacialteido:npathtorequestedtarget

This means the LDAP server’s certificate (or its CA) is not trusted by Keycloak’s Java runtime.

Critical Keycloak gotcha: The admin console’s Test Connection button only tests TCP socket connectivity. It does NOT test the TLS handshake. So “Test Connection” passes, but “Test Authentication” fails with SSLHandshakeException.

Fix for Keycloak 22+ (Quarkus):

# Step 1: Extract the CA certificate from the LDAP server
openssl s_client -connect ad.example.com:636 -showcerts </dev/null 2>/dev/null \
  | openssl x509 -outform PEM > /opt/keycloak/conf/truststores/ldap-ca.pem

# Step 2: Restart Keycloak — it auto-loads PEM files from conf/truststores/
bin/kc.sh start

Fix for older Keycloak (or JKS preference):

# Step 1: Extract the certificate
openssl s_client -connect ad.example.com:636 -showcerts </dev/null 2>/dev/null \
  | openssl x509 -outform PEM > ldap-ca.pem

# Step 2: Import into a Java keystore
keytool -importcert -trustcacerts \
  -alias ldap-ca \
  -file ldap-ca.pem \
  -keystore /opt/keycloak/conf/truststore.jks \
  -storepass changeit \
  -noprompt

# Step 3: Configure Keycloak to use the truststore
bin/kc.sh start \
  --spi-truststore-file-file=/opt/keycloak/conf/truststore.jks \
  --spi-truststore-file-password=changeit

Docker / Kubernetes:

# Docker: Mount the certificate and restart
docker run \
  -v /path/to/ldap-ca.pem:/opt/keycloak/conf/truststores/ldap-ca.pem:ro \
  quay.io/keycloak/keycloak:latest start

# Kubernetes: Create a secret and mount to conf/truststores/
kubectl create secret generic ldap-ca-cert \
  --from-file=ldap-ca.pem=/path/to/ldap-ca.pem

SAN Hostname Mismatch

jmaavtacxh.innegt.IsPsla.dSdSrLeHsasndXs.hXa.kXe.EXxcfeoputnidon:Nosubjectalternativenames

The Connection URL uses an IP address, but the certificate only has hostnames in the Subject Alternative Name (SAN) field.

Fix: Use the FQDN in the Connection URL, not the IP address:

#l#lddWaCaRpOpOsRsN:R:G/E//C/1Ta0d..0c.o1r.p5.0e:x6a3m6ple.com:636

Diagnosing TLS Issues

# View the full certificate chain
openssl s_client -connect ad.example.com:636 -showcerts </dev/null

# Check certificate expiration date
openssl s_client -connect ad.example.com:636 </dev/null 2>/dev/null \
  | openssl x509 -noout -dates

# View SAN entries (verify hostname matches)
openssl s_client -connect ad.example.com:636 </dev/null 2>/dev/null \
  | openssl x509 -noout -text | grep -A1 "Subject Alternative Name"

# Test StartTLS on port 389
openssl s_client -connect ad.example.com:389 -starttls ldap -showcerts </dev/null

StartTLS Disables Connection Pooling

Java’s JNDI implementation does not support connection pooling with StartTLS. If you use StartTLS (ldap:// on port 389 with TLS upgrade), Keycloak creates a new connection for every LDAP operation, causing severe performance degradation under load.

Fix: Use LDAPS (ldaps:// on port 636) instead of StartTLS if you need connection pooling.

Search and Sync Errors

PartialResultException — AD Referrals

jraevmaaxi.nnianmginnga.mPear'tOiUa=lURseesrusl,tDECx=cceoprtpi,oDnC:=eUxnapmrpolcee,sDsCe=dcoCmo'ntinuationReference(s);

This is an Active Directory multi-domain forest issue. When the search base spans multiple domains, AD returns referrals (pointers to other domain controllers) instead of results. Keycloak does not follow referrals by default.

Fix Option 1 — Use Global Catalog (recommended for multi-domain):

ConnectionURL:ldap://ad.example.com:3268orldaps://ad.example.com:3269)

Note: Global Catalog returns a limited subset of attributes. Custom attributes and passwords are not available through Global Catalog.

Fix Option 2 — Narrow the search base:

#U#UssIeUenrsrssesteDtDaNhNd:e:oDsOfCpU=e=tccEhoimerfppilf,cooDyrCdee=oesemstxa,aiDrmnCop:=olsteu:,bDdCo=mcaoimn,DC=corp,DC=example,DC=com

SizeLimitExceededException

javax.naming.SizeLimitExceededException:[LDAP:errorcode4-SizelimitExceeded]

Active Directory has a default size limit of 1000 entries per search. If your directory has more than 1000 users, this error occurs unless pagination is enabled.

Fix: Enable Pagination in the Keycloak LDAP provider settings (Admin Console → User Federation → LDAP → Pagination = ON).

Sync Reports 0 Imported, 0 Updated

WUApRdNat[eodr:g.0k,eyAcdldoeadk:.s0t,orFaagiel.eldd:ap0]Syncofusersfinished.

Causes:

  1. Users already exist in Keycloak — Users were created locally before LDAP federation was configured. They exist in Keycloak’s database but are not linked to the LDAP provider.
  2. Wrong Username LDAP Attribute — Must match the directory type:
DirectoryCorrect Username LDAP Attribute
Active DirectorysAMAccountName
OpenLDAPuid
FreeIPAuid
  1. Custom User LDAP Filter too restrictive — Test your filter with ldapsearch to verify it returns expected users.

TimeLimitExceededException

javax.naming.TimeLimitExceededException:[LDAP:errorcode3-TimeLimitExceeded]

The search is taking too long. Add a Custom User LDAP Filter to narrow results, or increase the LDAP server’s search time limit.

Password Change Errors

WILL_NOT_PERFORM (Error Code 53)

j[aLvDaAxP.:naemrirnogr.Ocpoedreat5i3on-No0t0S0u0p0p0o1rFt:edSEvxccEerprt:ioDnS:ID-031A1262,problem5003(WILL_NOT_PERFORM)]

Active Directory requires LDAPS for password change operations. Attempting to change a password over a non-SSL connection triggers this error.

Fix:

  1. Use ldaps:// (port 636) instead of ldap:// (port 389)
  2. Ensure the bind account has “Reset Password” permission on the target user objects
  3. Set Edit Mode to WRITABLE in Keycloak LDAP settings

Insufficient Access Rights (Error Code 50)

javax.naming.NoPermissionException:[LDAP:errorcode50-InsufficientAccessRights]

The bind account does not have write permissions, but Keycloak’s Edit Mode is set to WRITABLE.

Fix: Either grant the bind account the required AD permissions (Write userAccountControl, Write pwdLastSet, Reset password) or set Edit Mode to READ_ONLY.

Group Mapper Errors

Wrong Group Object Classes

Groups sync but clicking a group in Keycloak admin raises errors. This happens when the Group Object Classes setting doesn’t match your directory:

DirectoryCorrect Group Object Classes
Active Directorygroup
OpenLDAPgroupOfNames
FreeIPAgroupofnames

Empty Member Attribute Bug

LDAP groups with an empty member: attribute crash the group mapper in Keycloak versions before 22.0.3. Upgrade Keycloak or clean up empty groups in the LDAP directory.

Active Directory vs OpenLDAP vs FreeIPA

Configuration differs significantly across directory types. Using wrong values is the most common source of errors:

SettingActive DirectoryOpenLDAPFreeIPA
VendorActive DirectoryOtherRed Hat Directory Server
Username AttributesAMAccountNameuiduid
UUID AttributeobjectGUIDentryUUIDipaUniqueID
User Object Classesperson, organizationalPerson, userinetOrgPerson, organizationalPersoninetOrgPerson, organizationalPerson, person
Users DNCN=Users,DC=corp,DC=comou=people,dc=example,dc=comcn=users,cn=accounts,dc=example,dc=com
Group Object ClassesgroupgroupOfNamesgroupofnames
PaginationRequired (1000 limit)OptionalOptional
Password changesLDAPS requiredDepends on configLDAPS recommended

AD-Specific Pitfalls

  • Account lockout during testing — “Test Authentication” counts as a login attempt
  • UPN vs DN for bind — AD accepts both [email protected] (UPN) and full DN
  • Referrals in multi-domain forests — Causes PartialResultException (use Global Catalog port 3268/3269)
  • Password changes require LDAPS — Error code 53 WILL_NOT_PERFORM on non-SSL connections

OpenLDAP-Specific Pitfalls

  • No built-in pagination — Disable pagination in Keycloak if you get SizeLimitExceededException on OpenLDAP
  • entryUUID availability — May require the entryUUID overlay on older OpenLDAP versions
  • Plaintext passwords — OpenLDAP stores passwords in plaintext unless ppolicy overlay is configured

FreeIPA-Specific Pitfalls

  • UUID attribute — Must manually change to ipaUniqueID (Keycloak does not auto-detect)
  • Users DN structure — Note the cn=accounts level: cn=users,cn=accounts,dc=example,dc=com

Debug Logging

Enable Keycloak LDAP Trace Logging

# CLI startup parameter
bin/kc.sh start --log-level="INFO,org.keycloak.storage.ldap:TRACE"

# Environment variable
export KC_LOG_LEVEL="INFO,org.keycloak.storage.ldap:TRACE"

# In conf/keycloak.conf
log-level=INFO,org.keycloak.storage.ldap:TRACE

# Docker
docker run -e KC_LOG_LEVEL="INFO,org.keycloak.storage.ldap:TRACE" \
  quay.io/keycloak/keycloak:latest start

Enable TLS/SSL Debug Output

# Full SSL debug (very verbose)
export JAVA_OPTS="-Djavax.net.debug=all"

# SSL handshake only (recommended for troubleshooting)
export JAVA_OPTS="-Djavax.net.debug=ssl:handshake"

# Docker
docker run \
  -e KC_LOG_LEVEL="INFO,org.keycloak.storage.ldap:TRACE" \
  -e JAVA_OPTS="-Djavax.net.debug=ssl:handshake" \
  quay.io/keycloak/keycloak:latest start

Admin Console Gotcha: Save Before Testing

If you change the Connection URL or Bind Credential in the admin console and click “Test Authentication” without clicking “Save” first, Keycloak tests with the OLD saved values, not your new input. This causes false negatives and — if the old password is wrong — can lock out the bind account in Active Directory.

Always click Save before clicking Test Connection or Test Authentication.

Complete Debugging Workflow

When any LDAP error occurs, work through this sequence:

Step 1: Test network connectivity

nc -zv ad.example.com 636

Step 2: Test TLS/certificate chain

openssl s_client -connect ad.example.com:636 -showcerts </dev/null

Step 3: Test bind credentials

ldapsearch -x -H ldaps://ad.example.com:636 \
  -D "CN=keycloak-svc,CN=Users,DC=corp,DC=example,DC=com" \
  -W -b "DC=corp,DC=example,DC=com" "(sAMAccountName=testuser)"

Step 4: Enable debug logging and reproduce

bin/kc.sh start --log-level="INFO,org.keycloak.storage.ldap:TRACE"

Step 5: Check Keycloak events

Navigate to Admin Console → Events → Login Events → filter by REGISTER_ERROR or check server logs for org.keycloak.storage.ldap entries.