grpc/grpc-java · error · GrpcServiceParseException
Invalid initial metadata header: ${key}
Error message
Invalid initial metadata header: ${key} What it means
Thrown by GrpcServiceConfigParser.parse when an initial_metadata header from the GrpcService proto cannot be converted into a Metadata.HeaderValue — HeaderValue.create threw IllegalArgumentException (e.g. invalid header name characters) — or the header is rejected by HeaderValueValidationUtils.isDisallowed. gRPC forbids malformed or reserved headers in injected metadata.
Source
Thrown at xds/src/main/java/io/grpc/xds/GrpcServiceConfigParser.java:108
}
GrpcServiceConfig.GoogleGrpcConfig googleGrpcConfig =
parseGoogleGrpcConfig(grpcServiceProto.getGoogleGrpc(), bootstrapInfo, serverInfo);
GrpcServiceConfig.Builder builder = GrpcServiceConfig.builder().googleGrpc(googleGrpcConfig);
ImmutableList.Builder<HeaderValue> initialMetadata = ImmutableList.builder();
for (io.envoyproxy.envoy.config.core.v3.HeaderValue header : grpcServiceProto
.getInitialMetadataList()) {
String key = header.getKey();
HeaderValue headerValue;
try {
if (key.endsWith(Metadata.BINARY_HEADER_SUFFIX)) {
headerValue = HeaderValue.create(key, header.getRawValue());
} else {
headerValue = HeaderValue.create(key, header.getValue());
}
} catch (IllegalArgumentException e) {
throw new GrpcServiceParseException("Invalid initial metadata header: " + key, e);
}
if (HeaderValueValidationUtils.isDisallowed(headerValue)) {
throw new GrpcServiceParseException("Invalid initial metadata header: " + key);
}
initialMetadata.add(headerValue);
}
builder.initialMetadata(initialMetadata.build());
if (grpcServiceProto.hasTimeout()) {
com.google.protobuf.Duration timeout = grpcServiceProto.getTimeout();
if (!Durations.isValid(timeout) || Durations.compare(timeout, Durations.ZERO) <= 0) {
throw new GrpcServiceParseException("Timeout must be strictly positive and valid");
}
builder.timeout(Duration.ofSeconds(timeout.getSeconds(), timeout.getNanos()));
}
return builder.build();
}
View on GitHub (pinned to 64daddc1f3)
Solutions
- Fix the header key/value in the xDS resource: use lowercase, valid header names and legal values.
- Remove or rename disallowed/reserved headers (e.g. host, content-length) from initial_metadata.
- For binary data, use a key ending in '-bin' and supply raw_value instead of value.
- Inspect the GrpcService proto received from the control plane to identify the offending key named in the message.
Example fix
// before (xDS resource)
initial_metadata { key: "Host" value: "example.com" }
// after
initial_metadata { key: "x-custom-host" value: "example.com" } Defensive patterns
Strategy: validation
Validate before calling
// Pre-validate header keys before pushing them via xDS
String key = header.getKey();
if (key == null || key.isEmpty() || !key.chars().allMatch(c ->
(c >= 'a' && c <= '9' && c != ':') || c == '-' || (c >= '0' && c <= '9'))) {
throw new IllegalArgumentException("bad metadata header key: " + key);
} Try / catch
try {
config = GrpcServiceConfigParser.parse(proto, bootstrapInfo, serverInfo);
} catch (GrpcServiceParseException e) {
if (e.getMessage().startsWith("Invalid initial metadata header")) {
logger.log(WARNING, "Rejecting resource with bad header: " + e.getMessage());
}
} Prevention
- Use lowercase, RFC 7230-compliant header names in xDS metadata
- Use '-bin' suffixed keys with raw_value for binary data
- Avoid reserved gRPC/HTTP2 headers in initial_metadata
When it happens
Trigger: xDS GrpcService.google_grpc.call_credentials or channel config includes initial_metadata whose key is malformed (invalid characters, wrong case rules for binary headers missing the -bin suffix handling) or whose value fails validation; also fires when the header is on the disallowed list (e.g. reserved headers like :authority, host, content-length).
Common situations: Control-plane configuration injecting headers such as 'host', 'authorization' in disallowed forms, or binary values sent as regular (non -bin) headers; typos producing illegal ASCII control characters in keys.
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 header key:
- Timeout must be strictly positive and valid
- Target URI scheme is not resolvable: " + targetUri
- Failed to parse metadata key: %s, type: %s. Error: %s
AI-assisted analysis of grpc/grpc-java@64daddc1f3 (2026-09-08).
Data as JSON: /api/errors/b23702cef185e561.
Report an issue: GitHub.