grpc/grpc-java · error · GrpcServiceParseException
Invalid initial metadata header: " + key
Error message
Invalid initial metadata header: " + key
What it means
Second throw site with the same message as error 294, but without a cause: HeaderValue.create succeeded yet HeaderValueValidationUtils.isDisallowed returned true, meaning the header is structurally valid but on gRPC's disallowed header list. Injecting such headers via xDS metadata is rejected to preserve protocol invariants.
Source
Thrown at xds/src/main/java/io/grpc/xds/GrpcServiceConfigParser.java:111
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();
}
/**
* Parses the {@link io.envoyproxy.envoy.config.core.v3.GrpcService.GoogleGrpc} proto to create a
* {@link GrpcServiceConfig.GoogleGrpcConfig} instance.View on GitHub (pinned to 64daddc1f3)
Solutions
- Remove the disallowed header from initial_metadata in the xDS resource.
- Choose a custom application header name (e.g. prefix with x-) that passes validation.
- Consult HeaderValueValidationUtils / gRPC metadata spec for the disallowed header list.
Example fix
// before
initial_metadata { key: "content-type" value: "application/grpc" }
// after
initial_metadata { key: "x-content-type-hint" value: "application/grpc" } Defensive patterns
Strategy: validation
Validate before calling
// Check headers against disallowed list before configuring control plane
HeaderValue hv = HeaderValue.create(key, value);
if (HeaderValueValidationUtils.isDisallowed(hv)) {
throw new IllegalArgumentException("header disallowed by gRPC: " + key);
} Try / catch
try {
config = GrpcServiceConfigParser.parse(proto, bootstrapInfo, serverInfo);
} catch (GrpcServiceParseException e) {
logger.log(WARNING, "Resource rejected due to disallowed header: " + e.getMessage());
// request control plane to fix metadata
} Prevention
- Never inject reserved headers (host, te, content-type, content-length) via xDS
- Prefix custom headers with x-
- Review control-plane metadata templates against gRPC's disallowed header list
When it happens
Trigger: xDS GrpcService initial_metadata contains a well-formed header that gRPC disallows (reserved headers, restricted names). Distinct from 294 in that no IllegalArgumentException occurred — the header parses fine but is policy-forbidden.
Common situations: Control plane trying to inject 'te', 'content-type', 'host', or connection-level headers through initial_metadata; security policies forbidding credential headers being pushed via xDS.
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/6166a07e87a144b5.
Report an issue: GitHub.