spring-projects/spring-security · error · UnreachableFilterChainException

The FilterChainProxy contains two filter chains using the ma

Error message

The FilterChainProxy contains two filter chains using the matcher {defaultChain.getRequestMatcher()}

What it means

checkForDuplicateMatchers detects two SecurityFilterChain instances whose RequestMatchers are equal; the second chain is unreachable because the first always matches, so UnreachableFilterChainException is thrown with the duplicated matcher in the message.

Source

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

						+ "] 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(),
								filterChain, defaultChain);
					}
				}
			}
			if (chain instanceof DefaultSecurityFilterChain defaultChain) {
				filterChain = defaultChain;
			}
		}
	}

	private void checkAuthorizationFilters(List<SecurityFilterChain> chains) {
		Filter authorizationFilter = null;
		Filter filterSecurityInterceptor = null;
		for (SecurityFilterChain chain : chains) {
			for (Filter filter : chain.getFilters()) {
				if (filter instanceof AuthorizationFilter) {

View on GitHub (pinned to 96852e8860)

Solutions

  1. Give each chain a distinct securityMatcher pattern
  2. Remove the duplicate chain bean if it is not needed
  3. Differentiate the chains with @Order plus disjoint matchers so only one can match a given request

Example fix

// before
SecurityFilterChain api(HttpSecurity http) { http.securityMatcher("/api/**"); ... }
SecurityFilterChain apiCopy(HttpSecurity http) { http.securityMatcher("/api/**"); ... }
// after
SecurityFilterChain api(HttpSecurity http) { http.securityMatcher("/api/**"); ... }
SecurityFilterChain other(HttpSecurity http) { http.securityMatcher("/other/**"); ... }
Defensive patterns

Strategy: validation

Validate before calling

Set<RequestMatcher> seen = new HashSet<>();
for (SecurityFilterChain c : chains) {
    if (c instanceof DefaultSecurityFilterChain d && !seen.add(d.getRequestMatcher())) {
        throw new IllegalStateException("Duplicate matcher: " + d.getRequestMatcher());
    }
}

Try / catch

try {
    webSecurity.build();
} catch (UnreachableFilterChainException e) {
    if (e.getMessage().contains("two filter chains using the matcher")) {
        logger.error("Duplicate securityMatcher across chains: " + e.getMessage());
    }
    throw e;
}

Prevention

When it happens

Trigger: Publishing multiple SecurityFilterChain beans with identical securityMatcher patterns (e.g. two chains both matching /api/**); duplicated conditional configurations that both end up active; copying a chain without changing its matcher.

Common situations: Multiple WebSecurityConfigurerAdapter/SecurityFilterChain beans with copy-pasted matchers; profile-based configs where conditions overlap; generated configurations registering the same matcher twice.

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/1b8e89bbb8476276. Report an issue: GitHub.