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
- Check attribute repository configuration and confirm the user record exists and matches the query/filter.
- Fix the resolver so it supports the credential type emitted by the handler.
- Verify the authentication handler produces a usable principal, since CAS will fall back to it.
- 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
- Test search filters and base DNs against the live directory regularly.
- Decide explicitly whether handler-produced principals are an acceptable fallback.
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
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- Unable to grant access to
- Unable to detect the authentication principal for
- [ ] is configured to use [ ] but it does not support [ ]…
- Principal resolution handled by
- Principal resolution is unable to produce a result and will…
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)