apereo/cas · warning

Principal resolution handled by

Error message

Principal resolution handled by [{}] produced a null principal. This is likely due to misconfiguration or missing attributes; CAS will attempt to use the principal produced by the authentication handler, if any.

What it means

Non-fatal variant of the null-principal warning: principal resolution returned null, principalResolutionFailureFatal is false, so CAS logs that this is likely misconfiguration or missing attributes and will try to use the principal produced by the authentication handler, if any. Authentication continues but attributes may be incomplete.

Solutions

  1. Check attribute repository configuration and confirm the user record exists and matches the query/filter.
  2. Fix the resolver so it supports the credential type emitted by the handler.
  3. Verify the authentication handler produces a usable principal, since CAS will fall back to it.
  4. If missing principals are unacceptable, set cas.authn.principal-resolution-failure-fatal=true.

Example fix

// before
cas.authn.ldap[0].search-filter=(uid={user})  // user not present in that OU
// after
cas.authn.ldap[0].search-filter=(&(uid={user})(objectClass=person))  // corrected filter/base DN
Defensive patterns

Strategy: validation

Validate before calling

val attrs = attributeRepository.getPerson(user).getAttributes();
if (attrs.isEmpty()) {
    LOGGER.warn("No attributes found for {} — principal resolution will be null", user);
}

Prevention

When it happens

Trigger: resolvePrincipal returns null with principalResolutionFailureFatal=false; e.g. resolver unsupported credential, empty attribute query results, or handler produced no principal either.

Common situations: Attribute repository has no entry for the authenticated user; filter/query in attribute repository excludes the user; resolver credential mismatch (like 360) in lenient deployments; partially migrated configs after CAS version upgrades.

Understand the failure class

Related errors


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

Appendix: source

Thrown at core/cas-server-core-authentication-api/src/main/java/org/apereo/cas/authentication/DefaultAuthenticationManager.java:173

        try {
            AuthenticationHolder.setCurrentAuthentication(authenticationBuilder.build());
            val handlerExecutionResult = handler.authenticate(credential, service);
            val authenticationHandlerName = handler.getName();
            authenticationBuilder.addSuccess(authenticationHandlerName, handlerExecutionResult);
            LOGGER.debug("Authentication handler [{}] successfully authenticated [{}]", authenticationHandlerName, credential);
            publishEvent(new CasAuthenticationTransactionSuccessfulEvent(this, credential, clientInfo));
            var principal = principalResolver != null
                ? resolvePrincipal(handler, principalResolver, credential, handlerExecutionResult.getPrincipal(), service)
                : handlerExecutionResult.getPrincipal();
            if (principal == null) {
                val resolverName = principalResolver == null ? authenticationHandlerName : principalResolver.getName();
                if (this.principalResolutionFailureFatal) {
                    LOGGER.warn("Principal resolution handled by [{}] produced a null principal for: [{}]"
                        + "CAS is configured to treat principal resolution failures as fatal.", resolverName, credential);
                    throw new UnresolvedPrincipalException();
                }
                LOGGER.warn("Principal resolution handled by [{}] produced a null principal. "
                    + "This is likely due to misconfiguration or missing attributes; CAS will attempt to use the principal "
                    + "produced by the authentication handler, if any.", resolverName);
            } else {
                val currentPrincipal = authenticationBuilder.getPrincipal();
                if (!(currentPrincipal instanceof NullPrincipal)) {
                    val merger = authenticationSystemSupport.getObject().getPrincipalElectionStrategy().getAttributeMerger();
                    LOGGER.trace("Merging attributes from [{}] into principal [{}]", principal, currentPrincipal);
                    val mergedAttributes = CoreAuthenticationUtils.mergeAttributes(currentPrincipal.getAttributes(), principal.getAttributes(), merger);
                    principal = principal.withAttributes(mergedAttributes);
                    LOGGER.debug("Merged attributes into principal [{}]", principal);
                }
                authenticationBuilder.setPrincipal(principal);
            }
            LOGGER.debug("Final principal resolved for this authentication event is [{}]", principal);
            publishEvent(new CasAuthenticationPrincipalResolvedEvent(this, Objects.requireNonNull(principal), clientInfo));
        } finally {
            AuthenticationHolder.clear();
        }

View on GitHub (pinned to e7288fc434)