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

  1. Set cas.authn.ldap[x].base-dn to the subtree containing user entries (e.g. ou=people,dc=example,dc=org)
  2. Verify YAML indentation/nesting so base-dn is inside the same ldap[x] block
  3. 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

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.

Related errors


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)