apereo/cas · error · IllegalArgumentException
Base dn cannot be empty/blank for authenticated/anonymous…
Error message
Base dn cannot be empty/blank for authenticated/anonymous authentication
What it means
getAuthenticatedOrAnonSearchAuthenticator builds a search-then-bind Authenticator that must know where to look up users. It rejects a blank baseDn with IllegalArgumentException because neither authenticated nor anonymous search can proceed without a search base.
Solutions
- Set cas.authn.ldap[x].base-dn to the subtree containing user entries (e.g. ou=people,dc=example,dc=org)
- Verify YAML indentation/nesting so base-dn is inside the same ldap[x] block
- If you intend direct bind (DN pattern) instead, switch the bind/authentication type so this path is not taken
Example fix
// before cas.authn.ldap[0].base-dn= // after cas.authn.ldap[0].base-dn=ou=people,dc=example,dc=org
Defensive patterns
Strategy: validation
Validate before calling
if (props.getBaseDn() == null || props.getBaseDn().isBlank()) {
throw new IllegalStateException("base-dn is required for authenticated/anonymous LDAP search");
} Try / catch
try {
Authenticator a = LdapUtils.newLdaptiveAuthenticator(props);
} catch (IllegalArgumentException e) {
if (e.getMessage().contains("Base dn cannot be empty/blank")) {
// abort wiring and report the missing base-dn config
}
} Prevention
- Never leave base-dn blank in search-and-bind configurations
- Verify YAML nesting places base-dn inside the correct ldap[x] block
- For DN-pattern direct bind, use the direct-bind type instead of search types
- Validate the base DN with ldapsearch before rollout
When it happens
Trigger: Configuring an LDAP authentication type that resolves to authenticated/anonymous search (e.g. AUTHENTICATED, ANONYMOUS search types) while cas.authn.ldap[x].base-dn is unset or empty, then newLdaptiveAuthenticator is invoked.
Common situations: YAML block created from a template with base-dn left blank; direct-bind-style config reused for search-and-bind; property indentation wrong so base-dn lands in the wrong block; programmatic property construction skipping setBaseDn.
Understand the failure class
Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- LDAP url cannot be empty/blank
- User filter cannot be empty/blank for…
- Principal id attribute is not found for [principalAttr]
- Multiple principal values are not allowed: [principalAttr]
- Could not locate an LDAP entry for [filter] and base DN…
AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08).
Data as JSON: /api/errors/bb9529ed67ca092f.
Report an issue: GitHub.
Appendix: source
Thrown at support/cas-server-support-ldap-core/src/main/java/org/apereo/cas/util/LdapUtils.java:785
searchResultHandlers.add(
new RecursiveResultHandler(recursive.getSearchAttribute(),
recursive.getMergeAttributes().toArray(ArrayUtils.EMPTY_STRING_ARRAY)));
}
default -> searchResultHandlers.add(new MergeResultHandler());
}
});
return searchResultHandlers;
}
/**
* Gets authenticated authenticator.
*
* @param properties the lDAP properties
* @return the authenticated or anon search authenticator
*/
public static Authenticator getAuthenticatedOrAnonSearchAuthenticator(final AbstractLdapAuthenticationProperties properties) {
if (StringUtils.isBlank(properties.getBaseDn())) {
throw new IllegalArgumentException("Base dn cannot be empty/blank for authenticated/anonymous authentication");
}
if (StringUtils.isBlank(properties.getSearchFilter())) {
throw new IllegalArgumentException("User filter cannot be empty/blank for authenticated/anonymous authentication");
}
val connectionFactory = newLdaptiveConnectionFactory(properties);
val resolver = buildAggregateDnResolver(properties, connectionFactory);
val auth = StringUtils.isBlank(properties.getPrincipalAttributePassword())
? new Authenticator(resolver, getBindAuthenticationHandler(connectionFactory))
: new Authenticator(resolver, getCompareAuthenticationHandler(properties, connectionFactory));
if (properties.isEnhanceWithEntryResolver()) {
auth.setEntryResolver(newLdaptiveSearchEntryResolver(properties, connectionFactory));
}
return auth;
}
private static Authenticator getDnFormatAuthenticator(final AbstractLdapAuthenticationProperties properties) {View on GitHub (pinned to e7288fc434)