spring-projects/spring-security · error · UnreachableFilterChainException

A filter chain that matches any request [{anyRequestFilterCh

Error message

A filter chain that matches any request [{anyRequestFilterChain}] has already been configured, which means that this filter chain [{chain}] will never get invoked. Please use `HttpSecurity#securityMatcher` to ensure that there is only one filter chain configured for 'any request' and that the 'any request' filter chain is published last.

What it means

WebSecurityFilterChainValidator validates the published SecurityFilterChain list. checkForAnyRequestRequestMatcher throws UnreachableFilterChainException when a chain that matches any request (anyRequest()) is configured before another chain, because the earlier any-request chain will swallow every request and later chains can never run.

Source

Thrown at config/src/main/java/org/springframework/security/config/annotation/web/builders/WebSecurityFilterChainValidator.java:63

	private final Log logger = LogFactory.getLog(getClass());

	@Override
	public void validate(FilterChainProxy filterChainProxy) {
		List<SecurityFilterChain> chains = filterChainProxy.getFilterChains();
		checkForAnyRequestRequestMatcher(chains);
		checkForDuplicateMatchers(chains);
		checkAuthorizationFilters(chains);
	}

	private void checkForAnyRequestRequestMatcher(List<SecurityFilterChain> chains) {
		DefaultSecurityFilterChain anyRequestFilterChain = null;
		for (SecurityFilterChain chain : chains) {
			if (anyRequestFilterChain != null) {
				String message = "A filter chain that matches any request [" + anyRequestFilterChain
						+ "] has already been configured, which means that this filter chain [" + chain
						+ "] will never get invoked. Please use `HttpSecurity#securityMatcher` to ensure that there is only one filter chain configured for 'any request' and that the 'any request' filter chain is published last.";
				throw new UnreachableFilterChainException(message, anyRequestFilterChain, chain);
			}
			if (chain instanceof DefaultSecurityFilterChain defaultChain) {
				if (defaultChain.getRequestMatcher() instanceof AnyRequestMatcher) {
					anyRequestFilterChain = defaultChain;
				}
			}
		}
	}

	private void checkForDuplicateMatchers(List<SecurityFilterChain> chains) {
		DefaultSecurityFilterChain filterChain = null;
		for (SecurityFilterChain chain : chains) {
			if (filterChain != null) {
				if (chain instanceof DefaultSecurityFilterChain defaultChain) {
					if (defaultChain.getRequestMatcher().equals(filterChain.getRequestMatcher())) {
						throw new UnreachableFilterChainException(
								"The FilterChainProxy contains two filter chains using the" + " matcher "
										+ defaultChain.getRequestMatcher(),

View on GitHub (pinned to 96852e8860)

Solutions

  1. Order the chains so the anyRequest() chain is last (give it the lowest-priority @Order, e.g. @Order(Ordered.LOWEST_PRECEDENCE))
  2. Narrow the overly-broad chain with securityMatcher("/specific/**") instead of anyRequest()
  3. Remove the duplicate anyRequest chain if it is redundant

Example fix

// before
@Order(1)
SecurityFilterChain anyChain(HttpSecurity http) { http.authorizeHttpRequests(a -> a.anyRequest().authenticated()); ... }
// after
@Order(Ordered.LOWEST_PRECEDENCE)
SecurityFilterChain anyChain(HttpSecurity http) { http.authorizeHttpRequests(a -> a.anyRequest().authenticated()); ... }
Defensive patterns

Strategy: validation

Validate before calling

// before publishing chains, assert anyRequest chains are last
SecurityFilterChain last = chains.get(chains.size() - 1);
for (int i = 0; i < chains.size() - 1; i++) {
    if (matchesAnyRequest(chains.get(i))) {
        throw new IllegalStateException("anyRequest() chain must be the last published chain");
    }
}

Try / catch

try {
    webSecurity.build();
} catch (UnreachableFilterChainException e) {
    logger.error("Reorder your SecurityFilterChain beans: anyRequest chain must be last; offending: " + e.getMessage());
    throw e;
}

Prevention

When it happens

Trigger: Publishing two or more SecurityFilterChain beans where one uses anyRequest() and is not the last chain; multiple @SecurityFilterChain / WebSecurityConfigurerAdapter beans where the anyRequest chain is ordered first; misused @Order on filter chain beans.

Common situations: Microservice setups with multiple security configurations (API + actuator + default); copying a default anyRequest chain from samples alongside specialized chains; Spring Boot 5.8+ style multiple SecurityFilterChain beans with wrong @Order values.

Understand the failure class

Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.

Related errors


AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10). Data as JSON: /api/errors/913ad884c6cc2871. Report an issue: GitHub.