apereo/cas · warning

Attribute [ ] not found or has no values

Error message

Attribute [{}] not found or has no values

What it means

After finding the user's LDAP entry, SurrogateLdapAuthenticationService reads the configured member attribute (e.g. the multi-valued attribute listing accounts the user may impersonate). If the attribute is absent on the entry or has no values, this warning is logged and an empty surrogate account list is returned, blocking impersonation for that user.

Solutions

  1. Confirm member-attribute-name matches a real, populated attribute on the user entry (inspect with ldapsearch).
  2. Grant the user the surrogate membership values in LDAP per your provisioning process.
  3. Check the attribute's syntax (string vs binary) and LDAP schema mapping.
  4. Verify you are querying a current replica, not a lagging one.

Example fix

// before
cas.authn.surrogate.ldap[0].member-attribute-name=memberOf
// after
cas.authn.surrogate.ldap[0].member-attribute-name=casSurrogateMember
Defensive patterns

Strategy: validation

Validate before calling

Attributes attrs = entry.getAttributes();
if (attrs.get(memberAttr) == null || !attrs.get(memberAttr).getAll().hasMore()) {
    // user has no surrogate grants; skip impersonation path
}

Prevention

When it happens

Trigger: getImpersonationAccounts gets a valid LDAP entry but ldapEntry.getAttribute(memberAttributeName) returns null or attribute.getStringValues() is empty - the entry exists but was never populated with the surrogate member values.

Common situations: member-attribute-name misconfigured (typo or attribute not in schema); LDAP admins never granted the user impersonation rights; attribute stored as binary/different syntax so string values are empty; replication lag on a read replica.

Understand the failure class

Background: EmptyResultError / "no results found": when an API or scraper succeeds but returns zero rows — this error's family across 9 libraries.

Related errors


AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08). Data as JSON: /api/errors/bf5385b24d8c0963. Report an issue: GitHub.

Appendix: source

Thrown at support/cas-server-support-surrogate-authentication-ldap/src/main/java/org/apereo/cas/authentication/surrogate/SurrogateLdapAuthenticationService.java:84

        for (val ldap : ldapProperties) {
            try (val connectionFactory = new LdapConnectionFactory(LdapUtils.newLdaptiveConnectionFactory(ldap))) {
                val filter = LdapUtils.newLdaptiveSearchFilter(ldap.getSearchFilter(), CollectionUtils.wrap(username));
                LOGGER.debug("Using search filter to find eligible accounts: [{}]", filter);

                val response = connectionFactory.executeSearchOperation(ldap.getBaseDn(), filter, ldap.getPageSize());
                LOGGER.debug("LDAP response: [{}]", response);

                if (!LdapUtils.containsResultEntry(response)) {
                    LOGGER.warn("LDAP response is not found or does not contain a result entry for [{}]", username);
                    return new ArrayList<>();
                }

                val ldapEntry = response.getEntry();
                val attribute = ldapEntry.getAttribute(ldap.getMemberAttributeName());
                LOGGER.debug("Locating LDAP entry [{}] with attribute [{}]", ldapEntry, attribute);

                if (attribute == null || attribute.getStringValues().isEmpty()) {
                    LOGGER.warn("Attribute [{}] not found or has no values", ldap.getMemberAttributeName());
                    return new ArrayList<>();
                }

                val pattern = RegexUtils.createPattern(ldap.getMemberAttributeValueRegex());
                LOGGER.debug("Constructed attribute value regex pattern [{}]", pattern.pattern());
                val eligible = attribute.getStringValues()
                    .stream()
                    .map(pattern::matcher)
                    .filter(Matcher::matches)
                    .map(p -> {
                        if (p.groupCount() > 0) {
                            return p.group(1);
                        }
                        return p.group();
                    })
                    .sorted()
                    .collect(Collectors.toList());
                LOGGER.debug("Following accounts may be eligible for surrogate authentication: [{}]", eligible);

View on GitHub (pinned to e7288fc434)