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

  1. Remove the disallowed header from initial_metadata in the xDS resource.
  2. Choose a custom application header name (e.g. prefix with x-) that passes validation.
  3. 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

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


AI-assisted analysis of grpc/grpc-java@64daddc1f3 (2026-09-08). Data as JSON: /api/errors/6166a07e87a144b5. Report an issue: GitHub.