spring-projects/spring-security · error · IllegalStateException

@Order on WebSecurityConfigurers must be unique. Order of "…

Error message

@Order on WebSecurityConfigurers must be unique. Order of " + order + " was already used on " + previousConfig + ", so it cannot be used on " + config + " too.

What it means

Error "@Order on WebSecurityConfigurers must be unique. Order of " + order + " was already used on " + previousConfig + ", so it cannot be used on " + config + " too." thrown in spring-projects/spring-security.

Solutions

  1. Add a distinct @Order annotation to each WebSecurityConfigurer so no two share the same order value
  2. If two configurers intentionally share an order, merge them into a single SecurityConfigurer
  3. Use setOrder on the beans (e.g. via @Configuration ordering) to guarantee uniqueness before AutowiredWebSecurityConfigurersIgnoreParents sorts them
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at config/src/main/java/org/springframework/security/config/annotation/web/configuration/WebSecurityConfiguration.java:171 when the library encounters an invalid state.

Common situations: See trigger scenarios.


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

Appendix: source

Thrown at config/src/main/java/org/springframework/security/config/annotation/web/configuration/WebSecurityConfiguration.java:171

	 * @throws Exception
	 */
	@Autowired(required = false)
	public void setFilterChainProxySecurityConfigurer(ObjectPostProcessor<Object> objectPostProcessor,
			ConfigurableListableBeanFactory beanFactory) throws Exception {
		this.webSecurity = objectPostProcessor.postProcess(new WebSecurity(objectPostProcessor));
		if (this.debugEnabled != null) {
			this.webSecurity.debug(this.debugEnabled);
		}
		List<SecurityConfigurer<Filter, WebSecurity>> webSecurityConfigurers = new AutowiredWebSecurityConfigurersIgnoreParents(
				beanFactory)
			.getWebSecurityConfigurers();
		webSecurityConfigurers.sort(AnnotationAwareOrderComparator.INSTANCE);
		Integer previousOrder = null;
		Object previousConfig = null;
		for (SecurityConfigurer<Filter, WebSecurity> config : webSecurityConfigurers) {
			Integer order = AnnotationAwareOrderComparator.lookupOrder(config);
			if (previousOrder != null && previousOrder.equals(order)) {
				throw new IllegalStateException("@Order on WebSecurityConfigurers must be unique. Order of " + order
						+ " was already used on " + previousConfig + ", so it cannot be used on " + config + " too.");
			}
			previousOrder = order;
			previousConfig = config;
		}
		for (SecurityConfigurer<Filter, WebSecurity> webSecurityConfigurer : webSecurityConfigurers) {
			this.webSecurity.apply(webSecurityConfigurer);
		}
	}

	@Autowired(required = false)
	void setFilterChains(List<SecurityFilterChain> securityFilterChains) {
		this.securityFilterChains = securityFilterChains;
	}

	@Autowired(required = false)
	void setWebSecurityCustomizers(List<WebSecurityCustomizer> webSecurityCustomizers) {
		this.webSecurityCustomizers = webSecurityCustomizers;

View on GitHub (pinned to 96852e8860)