grpc/grpc-java · error · IllegalArgumentException
Invalid ASCII characters in header value for key:
Error message
Invalid ASCII characters in header value for key:
What it means
gRPC-XDS validates that header values contain valid ASCII characters before attaching them to xDS requests. This IllegalArgumentException is thrown when the value contains non-ASCII characters and the header key does not end with '-bin' (binary headers are exempt since they are base64-encoded). It mirrors Envoy's header character validation.
Source
Thrown at xds/src/main/java/io/grpc/xds/internal/grpcservice/HeaderValueValidationUtils.java:50
* Throws {@link IllegalArgumentException} if invalid.
*/
public static void validateHeaderKey(String key) {
if (key == null || key.isEmpty() || key.length() > MAX_HEADER_LENGTH) {
throw new IllegalArgumentException("Invalid header key: " + key);
}
}
/**
* Validates that the header value is within allowed length and contains valid ASCII characters.
* Throws {@link IllegalArgumentException} if invalid.
*/
public static void validateHeaderValue(String key, String value) {
validateHeaderKey(key);
if (value == null || value.length() > MAX_HEADER_LENGTH) {
throw new IllegalArgumentException("Header value length exceeds maximum allowed length");
}
if (!key.endsWith("-bin") && !isValidAsciiHeaderValue(value)) {
throw new IllegalArgumentException(
"Invalid ASCII characters in header value for key: " + key);
}
}
/**
* Validates that the raw header value is within allowed length and contains valid ASCII
* characters. Throws {@link IllegalArgumentException} if invalid.
*/
public static void validateHeaderValue(String key, ByteString rawValue) {
validateHeaderKey(key);
if (rawValue == null || rawValue.size() > MAX_HEADER_LENGTH) {
throw new IllegalArgumentException("Header value length exceeds maximum allowed length");
}
if (!key.endsWith("-bin") && !isValidAsciiHeaderValue(rawValue.toStringUtf8())) {
throw new IllegalArgumentException(
"Invalid ASCII characters in header value for key: " + key);
}
}View on GitHub (pinned to 64daddc1f3)
Solutions
- Remove or transliterate non-ASCII characters from the header value before validation
- Rename the key to end with "-bin" and base64-encode the value if binary/UTF-8 data is required
- Sanitize the input with a regex filter to strip non-ASCII characters
- Wrap the call in try-catch to detect and report invalid header configuration
Example fix
// before
HeaderValueValidationUtils.validateHeaderValue("x-user-name", "José"); // non-ASCII
// after
String sanitized = "José".replaceAll("[^\\x20-\\x7E]", "");
HeaderValueValidationUtils.validateHeaderValue("x-user-name", sanitized); Defensive patterns
Strategy: validation
Validate before calling
boolean ok = key.endsWith("-bin") || value.chars().allMatch(c -> c >= 0x20 && c <= 0x7E);
if (!ok) throw new IllegalArgumentException("Non-ASCII in header '" + key + "'"); Type guard
static boolean isAsciiSafe(String key, String value) {
return key.endsWith("-bin") || value != null && value.chars().allMatch(c -> c >= 0 && c < 128);
} Try / catch
try {
HeaderValueValidationUtils.validateHeaderValue(key, value);
} catch (IllegalArgumentException e) {
log.error("Header '{}' contains invalid ASCII", key);
} Prevention
- Sanitize user/locale-derived data before putting it in headers
- Use -bin headers + base64 for non-ASCII data
- Beware UTF-8 punctuation from config files (smart quotes, BOM)
- Unit-test header builders with non-ASCII inputs
When it happens
Trigger: Calling validateHeaderValue(String key, String value) with a value containing non-ASCII bytes (e.g., UTF-8 text, smart quotes, emoji, CJK characters) on a key that does not end with "-bin".
Common situations: Users putting localized/UTF-8 strings (names, descriptions) into custom headers; config files saved as UTF-8 with BOM or curly quotes; copying values containing non-breaking spaces from docs.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- Header value length exceeds maximum allowed length
- Not implemented
- unsupported ExtAuthz service type: only grpc_service is supp
- Invalid ring hash function: " + ringHash.getHashFunction()
- Invalid duration in weighted round robin config: " + ex.getM
AI-assisted analysis of grpc/grpc-java@64daddc1f3 (2026-09-08).
Data as JSON: /api/errors/2a063f78cc8828b9.
Report an issue: GitHub.