spring-projects/spring-security · error · IllegalArgumentException

The Filter class does not have a registered order and…

Error message

The Filter class {filter.getClass().getName()} does not have a registered order and cannot be added without a specified order. Consider using addFilterBefore or addFilterAfter instead.

What it means

HttpSecurity.addFilter expects the filter's class to already have a registered order (i.e. it is a known Spring Security filter). For arbitrary custom filters there is no order, so addFilter throws this IllegalArgumentException directing you to addFilterBefore/addFilterAfter instead.

Solutions

  1. Replace addFilter with http.addFilterBefore(filter, SomeExistingSecurityFilter.class) or addFilterAfter
  2. Alternatively use addFilterAt(filter, ExistingSecurityFilter.class) to pin it to a known slot
  3. If the filter extends a built-in security filter, register the exact built-in class position and keep the subclass's effective order consistent

Example fix

// before
http.addFilter(new MyTokenFilter());
// after
http.addFilterBefore(new MyTokenFilter(), UsernamePasswordAuthenticationFilter.class);
Defensive patterns

Strategy: fallback

Validate before calling

Integer order = /* filter order registry lookup */;
if (order == null) {
    // use addFilterBefore/addFilterAfter instead of addFilter
}

Try / catch

try {
    http.addFilter(filter);
} catch (IllegalArgumentException e) {
    if (e.getMessage().contains("does not have a registered order")) {
        http.addFilterBefore(filter, UsernamePasswordAuthenticationFilter.class);
    } else throw e;
}

Prevention

When it happens

Trigger: Calling http.addFilter(new MyCustomFilter()) where MyCustomFilter is not a Spring Security filter with a registered comparator order; adding a subclass whose concrete class is unknown to the filter order registry.

Common situations: Porting XML <custom-filter> configs to Java config; developers assuming addFilter works like addFilterBefore; custom filters extending OncePerRequestFilter directly.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at config/src/main/java/org/springframework/security/config/annotation/web/builders/HttpSecurity.java:1846

	}

	private HttpSecurity addFilterAtOffsetOf(Filter filter, int offset, Class<? extends Filter> registeredFilter) {
		Integer registeredFilterOrder = this.filterOrders.getOrder(registeredFilter);
		if (registeredFilterOrder == null) {
			throw new IllegalArgumentException(
					"The Filter class " + registeredFilter.getName() + " does not have a registered order");
		}
		int order = registeredFilterOrder + offset;
		this.filters.add(new OrderedFilter(filter, order));
		this.filterOrders.put(filter.getClass(), order);
		return this;
	}

	@Override
	public HttpSecurity addFilter(Filter filter) {
		Integer order = this.filterOrders.getOrder(filter.getClass());
		if (order == null) {
			throw new IllegalArgumentException("The Filter class " + filter.getClass().getName()
					+ " does not have a registered order and cannot be added without a specified order. Consider using addFilterBefore or addFilterAfter instead.");
		}
		this.filters.add(new OrderedFilter(filter, order));
		return this;
	}

	/**
	 * Adds the Filter at the location of the specified Filter class. For example, if you
	 * want the filter CustomFilter to be registered in the same position as
	 * {@link UsernamePasswordAuthenticationFilter}, you can invoke:
	 *
	 * <pre>
	 * addFilterAt(new CustomFilter(), UsernamePasswordAuthenticationFilter.class)
	 * </pre>
	 *
	 * Registration of multiple Filters in the same location means their ordering is not
	 * deterministic. More concretely, registering multiple Filters in the same location
	 * does not override existing Filters. Instead, do not register Filters you do not

View on GitHub (pinned to 96852e8860)