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
- Order the chains so the anyRequest() chain is last (give it the lowest-priority @Order, e.g. @Order(Ordered.LOWEST_PRECEDENCE))
- Narrow the overly-broad chain with securityMatcher("/specific/**") instead of anyRequest()
- 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
- Give the anyRequest() chain @Order(Ordered.LOWEST_PRECEDENCE) and specific chains lower order values
- Use securityMatcher("/api/**") instead of anyRequest() on specialized chains
- Review all SecurityFilterChain beans when adding a new one; check ordering and matcher overlap
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
- The Filter class {registeredFilter.getName()} does not have
- The Filter class {filter.getClass().getName()} does not have
- The FilterChainProxy contains two filter chains using the ma
- Possible error: Filters at position <i> and <j> are both ins
- Cannot apply {configurer} to already built object
AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10).
Data as JSON: /api/errors/913ad884c6cc2871.
Report an issue: GitHub.