grpc/grpc-java · error · IllegalArgumentException
Header name length must be in range [1, 16384): ${length}
Error message
Header name length must be in range [1, 16384): ${length} What it means
The HeaderMatchInput constructor validates header names used as xDS HttpRequestHeaderMatchInput: a name must be non-empty and shorter than 16384 characters, matching HTTP header name limits. Names that are empty or too long cannot appear in a valid HTTP request, so the constructor rejects them immediately with IllegalArgumentException and the offending length.
Source
Thrown at xds/src/main/java/io/grpc/xds/internal/matcher/HeaderMatchInput.java:43
import io.grpc.Metadata;
import java.util.Locale;
/**
* MatchInput for extracting HTTP headers.
*/
final class HeaderMatchInput implements MatchInput {
private static final BaseEncoding BASE64 = BaseEncoding.base64();
private final String headerName;
private final Metadata.Key<byte[]> binaryKey;
private final Metadata.Key<String> stringKey;
static final String TYPE_URL =
"type.googleapis.com/envoy.type.matcher.v3.HttpRequestHeaderMatchInput";
HeaderMatchInput(String headerName) {
this.headerName = checkNotNull(headerName, "headerName");
if (headerName.isEmpty() || headerName.length() >= 16384) {
throw new IllegalArgumentException(
"Header name length must be in range [1, 16384): " + headerName.length());
}
if (!headerName.equals(headerName.toLowerCase(Locale.ROOT))) {
throw new IllegalArgumentException("Header name must be lowercase: " + headerName);
}
try {
if (headerName.endsWith(Metadata.BINARY_HEADER_SUFFIX)) {
this.binaryKey = Metadata.Key.of(headerName, Metadata.BINARY_BYTE_MARSHALLER);
this.stringKey = null;
} else {
this.binaryKey = null;
this.stringKey = Metadata.Key.of(headerName, Metadata.ASCII_STRING_MARSHALLER);
}
} catch (IllegalArgumentException e) {
throw new IllegalArgumentException("Invalid header name: " + headerName, e);
}
}
View on GitHub (pinned to 64daddc1f3)
Solutions
- Ensure the header name is a valid non-empty HTTP header name, e.g. "x-user-id".
- Validate length (1..16383) on the config producer before emitting the matcher input.
- Catch IllegalArgumentException around HeaderMatchInput construction and reject the config with the root cause.
Example fix
// before
new HeaderMatchInput("");
// after
if (name == null || name.isEmpty() || name.length() >= 16384) throw new ConfigException("bad header name");
new HeaderMatchInput(name); Defensive patterns
Strategy: validation
Validate before calling
if (name == null || name.isEmpty() || name.length() >= 16384)
throw new IllegalArgumentException("header name length must be in [1, 16384)"); Type guard
boolean isValidHeaderNameLength(String name) {
return name != null && !name.isEmpty() && name.length() < 16384;
} Try / catch
try { return new HeaderMatchInput(name); }
catch (IllegalArgumentException e) { logger.warn("bad header name", e); return null; } Prevention
- Validate header names against HTTP limits when configs are authored.
- Never emit empty header-name fields from generators.
- Fuzz config parsers with empty/oversized names in tests.
When it happens
Trigger: Constructing HeaderMatchInput with "" (length 0) or a name whose length() >= 16384; the check is headerName.isEmpty() || headerName.length() >= 16384.
Common situations: Config generators emitting empty header-name fields; pathological or corrupted xDS configs; programmatic construction with unvalidated user-supplied header names; truncation/concatenation bugs producing huge strings.
Related errors
- Header name must be lowercase: ${headerName}
- HttpConnectionManager with xff_num_trusted_hops unsupported
- HttpConnectionManager with original_ip_detection_extensions
- Missing HttpFilter in HttpConnectionManager.
- HttpConnectionManager contains duplicate HttpFilter: ${filte
AI-assisted analysis of grpc/grpc-java@64daddc1f3 (2026-09-08).
Data as JSON: /api/errors/a85cca4c600db780.
Report an issue: GitHub.