grpc/grpc-java · error · IllegalArgumentException
Invalid header matcher config: [grpc-] prefixed header name
Error message
Invalid header matcher config: [grpc-] prefixed header name is not allowed.
What it means
This error is thrown by RbacFilter.parseHeaderMatcher when an xDS RBAC policy's header matcher specifies a header name starting with the reserved 'grpc-' prefix. The gRPC-internal 'grpc-*' metadata keys are reserved for the transport and must not be matched by RBAC rules, so the config is rejected at parse time with IllegalArgumentException.
Source
Thrown at xds/src/main/java/io/grpc/xds/RbacFilter.java:325
switch (proto.getRuleCase()) {
case PATH:
return PathMatcher.create(MatcherParser.parseStringMatcher(proto.getPath()));
case RULE_NOT_SET:
default:
throw new IllegalArgumentException(
"Unknown path matcher rule type: " + proto.getRuleCase());
}
}
private static RequestedServerNameMatcher parseRequestedServerNameMatcher(
io.envoyproxy.envoy.type.matcher.v3.StringMatcher proto) {
return RequestedServerNameMatcher.create(MatcherParser.parseStringMatcher(proto));
}
private static AuthHeaderMatcher parseHeaderMatcher(
io.envoyproxy.envoy.config.route.v3.HeaderMatcher proto) {
if (proto.getName().startsWith("grpc-")) {
throw new IllegalArgumentException("Invalid header matcher config: [grpc-] prefixed "
+ "header name is not allowed.");
}
if (":scheme".equals(proto.getName())) {
throw new IllegalArgumentException("Invalid header matcher config: header name [:scheme] "
+ "is not allowed.");
}
return AuthHeaderMatcher.create(MatcherParser.parseHeaderMatcher(proto));
}
private static AuthenticatedMatcher parseAuthenticatedMatcher(
Principal.Authenticated proto) {
Matchers.StringMatcher matcher = MatcherParser.parseStringMatcher(proto.getPrincipalName());
return AuthenticatedMatcher.create(matcher);
}
private static DestinationPortMatcher createDestinationPortMatcher(int port) {
return DestinationPortMatcher.create(port);
}View on GitHub (pinned to 64daddc1f3)
Solutions
- Remove or rename the header matcher so it does not use a name starting with 'grpc-'
- Match on a non-reserved application header instead (e.g. custom 'x-' headers)
- Validate header names before submitting the xDS config to the management server
Example fix
// before
{"header": {"name": "grpc-timeout", "exactMatch": "10s"}}
// after
{"header": {"name": "x-request-tier", "exactMatch": "premium"}} Defensive patterns
Strategy: validation
Validate before calling
if (headerMatcher.getName().startsWith("grpc-")) {
throw new IllegalArgumentException("Reserved grpc- header name not allowed in RBAC matcher: " + headerMatcher.getName());
} Prevention
- Never reference grpc-* headers in RBAC header matchers
- Pre-validate all header matcher names against reserved prefixes before submitting xDS config
- Keep RBAC policies generated from templates that whitelist allowed header names
When it happens
Trigger: Parsing an xDS RBAC config (via parsePermission or parsePrincipal) whose v3 HeaderMatcher proto has name like 'grpc-timeout' or 'grpc-encoding'.
Common situations: Hand-written RBAC policy JSON/YAML copied from HTTP proxy configs that reference grpc-* headers; tools generating RBAC policies that include internal gRPC transport headers.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- Invalid header matcher config: header name [:scheme] is not
- unsupported ExtAuthz service type: only grpc_service is supp
- Invalid ring hash function: " + ringHash.getHashFunction()
- Custom LB config does not contain a JSON object
- Unknown permission rule case: " + permission.getRuleCase()
AI-assisted analysis of grpc/grpc-java@64daddc1f3 (2026-09-08).
Data as JSON: /api/errors/3c1925211c6eb6c3.
Report an issue: GitHub.