apereo/cas · error · IllegalArgumentException

List of candidate multifactor authentication providers is…

Error message

List of candidate multifactor authentication providers is empty

What it means

RankedMultifactorAuthenticationProviderSelector.resolve sorts and selects the highest-ranked MFA provider, and refuses to run with an empty candidate list, throwing IllegalArgumentException. An empty provider list means no MultifactorAuthenticationProvider matched the request, so ranking is meaningless.

Solutions

  1. Configure at least one MFA provider (e.g. cas.authn.mfa.gauth) and confirm its bean is present in the application context
  2. Guard the call: only invoke resolve when the provider collection is non-empty
  3. Check the registered service's multifactor policy for typos in provider ids
  4. Review provider filtering (GlobalAuthenticationPolicyAdaptorRanker / provider activation) so matching providers are not excluded

Example fix

// before
var provider = rankedSelector.resolve(providers, service, principal);
// after
if (providers == null || providers.isEmpty()) {
    return; // skip MFA selection, continue with base authentication
}
var provider = rankedSelector.resolve(providers, service, principal);
Defensive patterns

Strategy: validation

Validate before calling

Collection<MultifactorAuthenticationProvider> providers = ...;
if (providers == null || providers.isEmpty()) {
    throw new IllegalStateException("Configure an MFA provider (cas.authn.mfa.*) before selecting");
}

Try / catch

try {
    return selector.resolve(providers, service, principal);
} catch (IllegalArgumentException e) {
    logger.warn("No MFA providers configured; skipping MFA");
    return null;
}

Prevention

When it happens

Trigger: Calling resolve(providers, service, principal) with an empty Collection of providers — e.g. when the registered service's multifactor policy yields no active providers (no providers configured/enabled, or all filtered out by service MFA policy).

Common situations: cas.authn.mfa provider not configured/enabled in the environment while a service's MFA policy requests MFA; custom code invoking the selector directly with an unfiltered/empty collection; provider beans missing from the Spring context.

Understand the failure class

Background: EmptyResultError / "no results found": when an API or scraper succeeds but returns zero rows — this error's family across 9 libraries.

Related errors


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

Appendix: source

Thrown at core/cas-server-core-webflow-mfa-api/src/main/java/org/apereo/cas/web/flow/authentication/RankedMultifactorAuthenticationProviderSelector.java:30

/**
 * This is {@link RankedMultifactorAuthenticationProviderSelector}
 * that sorts providers based on their rank and picks the one with
 * the highest priority.
 *
 * @author Misagh Moayyed
 * @since 5.0.0
 */
@Slf4j
public class RankedMultifactorAuthenticationProviderSelector implements MultifactorAuthenticationProviderSelector {

    @Override
    public MultifactorAuthenticationProvider resolve(final Collection<MultifactorAuthenticationProvider> providers,
                                                     @Nullable final RegisteredService service,
                                                     final Principal principal) {
        val sorted = new ArrayList<>(providers);
        if (sorted.isEmpty()) {
            throw new IllegalArgumentException("List of candidate multifactor authentication providers is empty");
        }
        AnnotationAwareOrderComparator.sort(sorted);
        return selectMultifactorAuthenticationProvider(service, sorted);
    }

    protected MultifactorAuthenticationProvider selectMultifactorAuthenticationProvider(
        @Nullable final RegisteredService service,
        final List<MultifactorAuthenticationProvider> providers) {
        val provider = providers.getLast();
        LOGGER.debug("Selected the provider [{}] for service [{}] out of [{}] providers", provider, service, providers.size());
        return provider;
    }
}

View on GitHub (pinned to e7288fc434)