spring-projects/spring-security · warning
Possible error: Filters at position <i> and <j> are both ins
Error message
Possible error: Filters at position <i> and <j> are both instances of <clazz.getName()>
What it means
DefaultFilterChainValidator.checkFilterStack scans the Spring Security filter chain and warns when two filters at different positions are both instances of the same configured filter class. Duplicate filters in the chain are almost always a configuration error that causes the filter to run twice (double authentication, double logging, order confusion). This is a logged warning, not an exception.
Source
Thrown at config/src/main/java/org/springframework/security/config/http/DefaultFilterChainValidator.java:179
checkForDuplicates(BasicAuthenticationFilter.class, filters);
checkForDuplicates(SecurityContextHolderAwareRequestFilter.class, filters);
checkForDuplicates(JaasApiIntegrationFilter.class, filters);
checkForDuplicates(ExceptionTranslationFilter.class, filters);
if (USING_ACCESS) {
checkForDuplicates(AccessComponents.getFilterSecurityInterceptorClass(), filters);
}
checkForDuplicates(AuthorizationFilter.class, filters);
}
private void checkForDuplicates(Class<? extends Filter> clazz, List<Filter> filters) {
for (int i = 0; i < filters.size(); i++) {
Filter f1 = filters.get(i);
if (clazz.isAssignableFrom(f1.getClass())) {
// Found the first one, check remaining for another
for (int j = i + 1; j < filters.size(); j++) {
Filter f2 = filters.get(j);
if (clazz.isAssignableFrom(f2.getClass())) {
this.logger.warn("Possible error: Filters at position " + i + " and " + j + " are both "
+ "instances of " + clazz.getName());
return;
}
}
}
}
}
/*
* Checks for the common error of having a login page URL protected by the security
* interceptor
*/
private void checkLoginPageIsntProtected(FilterChainProxy fcp, List<Filter> filterStack) {
ExceptionTranslationFilter exceptions = getFilter(ExceptionTranslationFilter.class, filterStack);
if (exceptions == null
|| !(exceptions.getAuthenticationEntryPoint() instanceof LoginUrlAuthenticationEntryPoint)) {
return;
}View on GitHub (pinned to 96852e8860)
Solutions
- Remove the manual registration if Spring Security already inserts that filter by default.
- Use addFilterBefore/addFilterAfter with a distinct custom class instead of re-registering a stock filter.
- Log the full filter chain (enable debug logging for FilterChainProxy) and delete the duplicate entry.
- If intentional, verify idempotency or subclass the filter so classes differ.
Example fix
// before: duplicate http.addFilter(new UsernamePasswordAuthenticationFilter()); http.formLogin(Customizer.withDefaults()); // after: rely on DSL registration http.formLogin(Customizer.withDefaults());
Defensive patterns
Strategy: validation
Validate before calling
// detect duplicate filter classes before enabling the chain
Set<Class<?>> seen = new HashSet<>();
for (Filter f : filters) {
if (!seen.add(f.getClass())) {
throw new IllegalStateException("Duplicate filter: " + f.getClass().getName());
}
} Prevention
- Prefer the securityFilterChain DSL over manual addFilter for stock filters.
- Review startup logs for 'Possible error: Filters at position' warnings.
- Write a test asserting the exact expected filter-chain order.
- When inserting filters, choose addFilterBefore/After targets that are not themselves duplicated.
When it happens
Trigger: Calling validate() on a FilterChainProxy whose security filter list contains two instances assignable to the same filter class, e.g. manually adding a filter that the namespace/DSL already registers, or declaring the same filter bean twice.
Common situations: Adding a custom or stock filter (e.g. UsernamePasswordAuthenticationFilter, CsrfFilter) via addFilterBefore/After when it is already in the chain; copying namespace config from XML to Java config and double-registering; multiple http blocks each adding the same filter.
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
- A filter chain that matches any request [{anyRequestFilterCh
- The FilterChainProxy contains two filter chains using the ma
- Object identity '{objectIdentity}' already exists
AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10).
Data as JSON: /api/errors/ff2baa3b8373f298.
Report an issue: GitHub.