spring-projects/spring-security · error · ServerExchangeRejectedException

The was rejected because it can only contain printable…

Error message

The %s was rejected because it can only contain printable ASCII characters.

What it means

StrictServerWebExchangeFirewall rejects requests whose field values (URL path or query string, via rejectNonPrintableAsciiCharactersInFieldName) contain characters outside the printable ASCII range. The check calls containsOnlyPrintableAsciiCharacters and throws ServerExchangeRejectedException naming the offending property. This prevents control characters and non-ASCII bytes from sneaking into request fields.

Solutions

  1. Percent-encode non-ASCII characters client-side (URLEncoder / encodeURIComponent) before building the URL.
  2. Identify the offending field from the exception message and sanitize the source of that input.
  3. Validate/sanitize input at an upstream gateway to strip control characters before the request reaches Spring.
  4. Avoid disabling the check (it is internal); if legitimate Unicode is needed, ensure it is properly encoded so the raw field stays printable ASCII.

Example fix

// before
const url = `/api/search?q=${term}`; // term may contain raw Unicode/control chars
// after
const url = `/api/search?q=${encodeURIComponent(term)}`;
Defensive patterns

Strategy: validation

Validate before calling

// JavaScript client-side guard
if (!/^[\x20-\x7E]*$/.test(param)) {
    param = encodeURIComponent(param);
}

Try / catch

@ExceptionHandler(ServerExchangeRejectedException.class)
Mono<Void> handle(ServerWebExchange exchange, ServerExchangeRejectedException e) {
    log.warn("Rejected non-ASCII field: {}", e.getMessage());
    exchange.getResponse().setStatusCode(HttpStatus.BAD_REQUEST);
    return exchange.getResponse().setComplete();
}

Prevention

When it happens

Trigger: A request URL or query parameter contains non-printable ASCII (control characters) or non-ASCII (e.g. UTF-8 multibyte) characters that were not percent-encoded, and the firewall validates the field during getFirewalledExchange.

Common situations: Users typing Unicode into URL parameters that a client fails to encode; scanners sending %00/\x00 payloads; legacy clients putting raw bytes in the query string; logging tools revealing unexpected characters in access logs.

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

Appendix: source

Thrown at web/src/main/java/org/springframework/security/web/server/firewall/StrictServerWebExchangeFirewall.java:567

	 */
	public void setAllowedHostnames(Predicate<String> allowedHostnames) {
		Assert.notNull(allowedHostnames, "allowedHostnames cannot be null");
		this.allowedHostnames = allowedHostnames;
	}

	private void urlBlocklistsAddAll(Collection<String> values) {
		this.encodedUrlBlocklist.addAll(values);
		this.decodedUrlBlocklist.addAll(values);
	}

	private void urlBlocklistsRemoveAll(Collection<String> values) {
		this.encodedUrlBlocklist.removeAll(values);
		this.decodedUrlBlocklist.removeAll(values);
	}

	private void rejectNonPrintableAsciiCharactersInFieldName(String toCheck, String propertyName) {
		if (!containsOnlyPrintableAsciiCharacters(toCheck)) {
			throw new ServerExchangeRejectedException(String
				.format("The %s was rejected because it can only contain printable ASCII characters.", propertyName));
		}
	}

	private void rejectForbiddenHttpMethod(ServerHttpRequest request) {
		if (this.allowedHttpMethods == ALLOW_ANY_HTTP_METHOD) {
			return;
		}
		if (!this.allowedHttpMethods.contains(request.getMethod())) {
			throw new ServerExchangeRejectedException(
					"The request was rejected because the HTTP method \"" + request.getMethod()
							+ "\" was not included within the list of allowed HTTP methods " + this.allowedHttpMethods);
		}
	}

	private void rejectedBlocklistedUrls(ServerHttpRequest request) {
		for (String forbidden : this.encodedUrlBlocklist) {
			if (encodedUrlContains(request, forbidden)) {

View on GitHub (pinned to 96852e8860)