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
- Percent-encode non-ASCII characters client-side (URLEncoder / encodeURIComponent) before building the URL.
- Identify the offending field from the exception message and sanitize the source of that input.
- Validate/sanitize input at an upstream gateway to strip control characters before the request reaches Spring.
- 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
- Percent-encode all non-ASCII data in URLs
- Strip control characters from user input before building URLs
- Reject or sanitize input at the API gateway too
- Avoid raw bytes in query strings from legacy clients
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
- The request was rejected because the HTTP method
- The was rejected because it can only contain printable…
- The request was rejected because the URL contained a…
- The request was rejected because the URL was not normalized
- The requestURI cannot contain encoded slash. Got " +…
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)