spring-projects/spring-security · error · IllegalArgumentException
Spring Security and Spring MVC must use the same path…
Error message
Spring Security and Spring MVC must use the same path pattern parser. To have Spring Security use Spring MVC's [{mvcParser}] simply publish this bean [{thisBean}] using its default constructor What it means
PathPatternRequestMatcherBuilderFactoryBean aligns Spring Security's request-matching with Spring MVC's PathPatternParser. If the effective parser (custom injected parser or default) differs from the one Spring MVC uses in the context, getObject() throws IllegalArgumentException because security and MVC would interpret URL paths differently.
Solutions
- Publish PathPatternRequestMatcher.Builder using its default constructor so it adopts Spring MVC's parser
- Change the custom parser so it equals the MVC parser instance/config
- If MVC's parser must differ, adjust MVC pathmatch configuration so both sides match
Example fix
// before
@Bean
PathPatternRequestMatcher.Builder securityMatcherBuilder() {
return new PathPatternRequestMatcher.Builder(PathPatternParser.defaultInstance);
}
// after
@Bean
PathPatternRequestMatcher.Builder securityMatcherBuilder() {
return new PathPatternRequestMatcher.Builder(); // uses Spring MVC's parser
} Defensive patterns
Strategy: validation
Validate before calling
PathPatternParser mvc = context.getBean("webMvcPathPatternParser", PathPatternParser.class);
PathPatternParser securityParser = /* parser you configured */;
if (!mvc.equals(securityParser)) {
throw new IllegalStateException("Security and MVC path parsers differ; use the default constructor");
} Prevention
- Always use the PathPatternRequestMatcher.Builder default constructor in MVC apps
- Avoid custom PathPatternParser instances on the security side unless MVC uses the same one
- Keep spring.mvc.pathmatch.matching-strategy consistent with security matching
When it happens
Trigger: Publishing PathPatternRequestMatcher.Builder with a non-default constructor/parser (e.g. withPathPatternParser() with a different parser instance) while a Spring MVC PathPatternParser bean exists and they are not equal.
Common situations: Customizing the parser via a custom bean definition after upgrading to Spring Security 7; mixing AntPathMatcher-based settings with MVC's pathpattern matching; bootstrapping the builder with a constructor argument in a MVC app.
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
- A Bean named mvcHandlerMappingIntrospector of type…
- A Bean named mvcHandlerMappingIntrospector of type…
- principal + " is not assignable to " +…
- principal + " is not assignable to " +…
- A filter chain that matches any request
AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10).
Data as JSON: /api/errors/5331a6eb5f2a0b69.
Report an issue: GitHub.
Appendix: source
Thrown at config/src/main/java/org/springframework/security/config/web/PathPatternRequestMatcherBuilderFactoryBean.java:89
* Please call the default constructor instead.
* @param parser the {@link PathPatternParser} to use
*/
public PathPatternRequestMatcherBuilderFactoryBean(PathPatternParser parser) {
this.parser = parser;
}
@Override
public PathPatternRequestMatcher.Builder getObject() throws Exception {
if (!this.context.containsBean(MVC_PATTERN_PARSER_BEAN_NAME)) {
PathPatternParser parser = (this.parser != null) ? this.parser : PathPatternParser.defaultInstance;
return withPathPatternParser(parser);
}
PathPatternParser mvc = this.context.getBean(MVC_PATTERN_PARSER_BEAN_NAME, PathPatternParser.class);
PathPatternParser parser = (this.parser != null) ? this.parser : mvc;
if (mvc.equals(parser)) {
return withPathPatternParser(parser);
}
throw new IllegalArgumentException("Spring Security and Spring MVC must use the same path pattern parser. "
+ "To have Spring Security use Spring MVC's [" + describe(mvc, MVC_PATTERN_PARSER_BEAN_NAME)
+ "] simply publish this bean [" + describe(this, this.beanName) + "] using its default constructor");
}
private PathPatternRequestMatcher.Builder withPathPatternParser(PathPatternParser parser) {
if (this.basePath == null) {
return PathPatternRequestMatcher.withPathPatternParser(parser);
}
else {
return PathPatternRequestMatcher.withPathPatternParser(parser).basePath(this.basePath);
}
}
@Override
public Class<?> getObjectType() {
return PathPatternRequestMatcher.Builder.class;
}
View on GitHub (pinned to 96852e8860)