grpc/grpc-java · error · IllegalArgumentException
Invalid header key:
Error message
Invalid header key:
What it means
HeaderValueValidationUtils.validateHeaderKey checks that a header key is non-null, non-empty, and within MAX_HEADER_LENGTH. Keys violating these rules cause an IllegalArgumentException including the offending key. It guards HTTP/2 header-name rules before ext_proc mutations are applied.
Source
Thrown at xds/src/main/java/io/grpc/xds/internal/grpcservice/HeaderValueValidationUtils.java:36
import com.google.protobuf.ByteString;
import java.util.Locale;
/**
* Utility class for validating HTTP headers.
*/
public final class HeaderValueValidationUtils {
public static final int MAX_HEADER_LENGTH = 16384;
private HeaderValueValidationUtils() {}
/**
* Validates that the header key is non-empty and within allowed length.
* 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);
}
}
View on GitHub (pinned to 64daddc1f3)
Solutions
- Fix the ext_proc server so every HeaderValue carries a valid, non-empty key within the length limit
- Validate/sanitize keys on the mutation producer before returning them
- Reject or log-and-skip invalid header mutations in your processor logic
- Keep header names short and lowercase per HTTP/2 conventions
Example fix
// before
HeaderValue.newBuilder().setValue("abc").build() // missing key
// after
HeaderValue.newBuilder().setKey("x-user-id").setValue("abc").build() Defensive patterns
Strategy: validation
Validate before calling
if (key == null || key.isEmpty() || key.length() > HeaderValueValidationUtils.MAX_HEADER_LENGTH) { rejectMutation(); } Type guard
null
Try / catch
try { HeaderValueValidationUtils.validateHeaderKey(key); }
catch (IllegalArgumentException e) { log.warn("Dropping invalid header mutation", e); } Prevention
- Always set a valid key on HeaderValue protos
- Validate header names before returning ext_proc mutations
- Follow HTTP/2 header-name rules (lowercase, no spaces)
When it happens
Trigger: validateHeaderKey (directly or via validateHeaderValue) receives a null key, an empty "" key, or a key longer than MAX_HEADER_LENGTH — typically from an ext_proc header-mutation response.
Common situations: ext_proc server returning HeaderValue protos with unset key; middleware constructing headers programmatically and forgetting the name; config-driven header injection with a blank key template.
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
- Invalid initial metadata header: ${key}
- Invalid initial metadata header: " + key
- Header value length exceeds maximum allowed length:
- Timeout must be strictly positive and valid
- Target URI scheme is not resolvable: " + targetUri
AI-assisted analysis of grpc/grpc-java@64daddc1f3 (2026-09-08).
Data as JSON: /api/errors/97530993f3cd3186.
Report an issue: GitHub.