apereo/cas · warning
Could not locate LDAP attribute
Error message
Could not locate LDAP attribute [{}] for [{}] What it means
The internal findAttribute helper searches the LDAP entry returned for the user and reads the requested attribute's string value. When the entry exists but does not contain the configured attribute (attr == null), it logs this warn and returns null, propagating 'attribute missing' to findEmails/findPhone/findUsername callers.
Solutions
- Verify the attribute exists and is populated on the user's DN in the directory (ldapsearch as the configured bind user)
- Fix cas.authn.pm.reset.mail.attributeName / sms.attributeName to match the directory schema exactly
- Extend the entry's objectClass or populate the attribute for affected users
- Check ACLs so the PM bind account can read the attribute
Example fix
// before cas.authn.pm.reset.sms.attributeName=telephoneNumber // entries only populate 'mobile' // after cas.authn.pm.reset.sms.attributeName=mobile
Defensive patterns
Strategy: fallback
Validate before calling
// pre-flight: confirm the attribute is readable before triggering flows
Attributes a = ctx.getAttributes(userDn, new String[]{attributeName});
if (a.get(attributeName) == null) {
log.warn("User {} has no {} attribute", userDn, attributeName);
} Try / catch
String v = pmService.findPhone(query);
if (v == null) { log.info("No phone attribute; falling back to email flow"); } Prevention
- ldapsearch with the PM bind account to confirm attribute visibility before configuring
- Match attributeName values exactly to directory schema (case included)
- Populate mail/mobile during account provisioning so PM always has a contact
When it happens
Trigger: LDAP search succeeds and returns the user's entry, but entry.get(attributeName) is null — the schema/objectClass of the entry simply has no value for the configured attribute name.
Common situations: cas.authn.pm.reset.mail/sms.attributeName points at an attribute the user entries never populate (e.g. mobile not set); attribute name typo or wrong case; entries belong to an objectClass lacking that attribute; attribute hidden by ACLs/anonymous search limits.
Understand the failure class
Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.
Related errors
- Email address [ ] for [ ] is not valid
- Invalid credentials
- [username] not found.
- Principal id attribute is not found for [principalAttr]
- Multiple principal values are not allowed: [principalAttr]
AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08).
Data as JSON: /api/errors/d8d94e4d9fe42bb8.
Report an issue: GitHub.
Appendix: source
Thrown at support/cas-server-support-pm-ldap/src/main/java/org/apereo/cas/pm/LdapPasswordManagementService.java:194
final List<String> attributeNames,
final List<String> ldapFilterParam) {
return findEntries(ldapFilterParam, false)
.keySet()
.stream()
.map(entry -> {
LOGGER.debug("Found LDAP entry [{}] to use", entry);
return attributeNames
.stream()
.map(attributeName -> SpringExpressionLanguageValueResolver.getInstance().resolve(attributeName))
.map(attributeName -> {
val attr = entry.getAttribute(attributeName);
if (attr != null) {
val attributeValue = attr.getStringValue();
LOGGER.debug("Found [{}] [{}] for user [{}].", attributeName,
attributeValue, context.getUsername());
return attributeValue;
}
LOGGER.warn("Could not locate LDAP attribute [{}] for [{}]",
attributeName, entry.getDn());
return null;
})
.filter(Objects::nonNull)
.findFirst()
.orElse(null);
})
.filter(Objects::nonNull)
.findFirst()
.orElse(null);
}
protected Map<LdapEntry, LdapPasswordManagementProperties> findEntries(
final List<String> filterValues, final boolean transform) {
val results = new LinkedHashMap<LdapEntry, LdapPasswordManagementProperties>();
casProperties.getAuthn().getPm().getLdap()
.stream()
.sorted(Comparator.comparing(LdapPasswordManagementProperties::getName))View on GitHub (pinned to e7288fc434)