apereo/cas · warning

[ ] is configured to use [ ] but it does not support [ ]…

Error message

[{}] is configured to use [{}] but it does not support [{}], which suggests a configuration problem.

What it means

In DefaultAuthenticationManager.resolvePrincipal, CAS skipped the configured PrincipalResolver because the resolver does not support the credential produced by the authentication handler. This is a warning indicating a wiring/misconfiguration: the handler and resolver credential types do not line up, so no principal resolution occurs and resolvePrincipal returns null.

Solutions

  1. Check the handler's returned credential type and ensure the configured PrincipalResolver.supports() includes that type.
  2. Remove or correct the mis-mapped resolver in the CAS configuration (cas.authn.*.principalResolver / principalTransformation settings).
  3. Register a resolver bean that explicitly declares support for the credential class, or rely on the default PersonDirectoryPrincipalResolver wiring.
  4. Enable debug logging for org.apereo.cas.authentication to see which handler/resolver pair is evaluated.

Example fix

// before
@Bean
public PrincipalResolver jdbcResolver(...) { /* supports only JwtCredential */ }
// after
@Bean
public PrincipalResolver personDirectoryPrincipalResolver() {
    return new PersonDirectoryPrincipalResolver(principalFactory, attributeRepository);
}
Defensive patterns

Strategy: validation

Validate before calling

if (!principalResolver.supports(credential)) {
    throw new IllegalStateException("Resolver " + principalResolver.getName()
        + " does not support credential " + credential.getClass().getSimpleName());
}

Prevention

When it happens

Trigger: A PrincipalHandlerResolver/PrincipalResolver was registered whose supports(credential) returns false for the credential emitted by the authentication handler; resolvePrincipal is reached during authenticateAndResolvePrincipal after a handler successfully authenticates.

Common situations: Configuring a resolver for credential type A (e.g. UsernamePasswordCredential) while the matched handler returns a different credential type; custom resolvers registered in the wrong module or overridden by @ConditionalOnMissingBean defaults; service-specific handler/resolver mappings where the resolver was defined for another authentication policy.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


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

Appendix: source

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

        authentication.getSuccesses().values()
            .forEach(result -> builder.addAttribute(AUTHENTICATION_METHOD_ATTRIBUTE, result.getHandlerName()));
    }

    protected @Nullable Principal resolvePrincipal(final AuthenticationHandler handler, final PrincipalResolver resolver,
                                                   final Credential credential, final Principal principal,
                                                   final Service service) {
        if (resolver.supports(credential)) {
            try {
                val resolved = resolver.resolve(credential, Optional.ofNullable(principal),
                    Optional.ofNullable(handler), Optional.ofNullable(service));
                LOGGER.debug("[{}] resolved [{}] from [{}]", resolver, resolved, credential);
                return resolved;
            } catch (final Throwable e) {
                LOGGER.error("[{}] failed to resolve principal from [{}]", resolver, credential);
                LoggingUtils.error(LOGGER, e);
            }
        } else {
            LOGGER.warn("[{}] is configured to use [{}] but it does not support [{}], which suggests a configuration problem.",
                handler.getName(), resolver, credential);
        }
        return null;
    }

    protected boolean invokeAuthenticationPreProcessors(final AuthenticationTransaction transaction) throws Throwable {
        LOGGER.trace("Invoking authentication pre processors for authentication transaction");
        val pops = authenticationEventExecutionPlan.getAuthenticationPreProcessors(transaction);

        val supported = pops.stream()
            .filter(processor -> transaction.getCredentials()
                .stream()
                .anyMatch(Unchecked.predicate(processor::supports)))
            .toList();

        var processed = true;
        val it = supported.iterator();
        while (processed && it.hasNext()) {

View on GitHub (pinned to e7288fc434)