grpc/grpc-java · error · IllegalArgumentException

Unknown path matcher rule type: " + proto.getRuleCase()

Error message

Unknown path matcher rule type: " + proto.getRuleCase()

What it means

An Envoy PathMatcher proto must have its 'rule' oneof set to PATH (with a StringMatcher). parsePathMatcher throws IllegalArgumentException when the oneof is RULE_NOT_SET or an unrecognized new case, because the RBAC url_path matchers cannot be built.

Source

Thrown at xds/src/main/java/io/grpc/xds/RbacFilter.java:312

      case URL_PATH:
        return parsePathMatcher(principal.getUrlPath());
      case METADATA: // hard coded, never match.
        return InvertMatcher.create(AlwaysTrueMatcher.INSTANCE);
      case IDENTIFIER_NOT_SET:
      default:
        throw new IllegalArgumentException(
                "Unknown principal identifier case: " + principal.getIdentifierCase());
    }
  }

  private static PathMatcher parsePathMatcher(
          io.envoyproxy.envoy.type.matcher.v3.PathMatcher proto) {
    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.");

View on GitHub (pinned to 64daddc1f3)

Solutions

  1. Set the path rule explicitly in the url_path matcher, e.g. {path: {prefix: "/api"}}
  2. Upgrade grpc-xds/envoy protos if a new rule case is being sent
  3. Replace unsupported path rule types with a supported StringMatcher form (prefix/exact/regex/safe_regex)
  4. Check the appended rule case in the message to see which case arrived

Example fix

# before
url_path: {}
# after
url_path:
  path: {prefix: "/api"}
Defensive patterns

Strategy: validation

Validate before calling

if (pathMatcher.getRuleCase() != PathMatcher.RuleCase.PATH) {
  throw new IllegalArgumentException("url_path matcher must set a path rule");
}

Try / catch

try {
  Matcher m = parsePathMatcher(proto);
} catch (IllegalArgumentException e) {
  logger.warning("Bad path matcher: " + e.getMessage());
  // reject the RBAC config containing it
}

Prevention

When it happens

Trigger: parsePermission or parsePrincipal process a Permission/Principal with a url_path field whose PathMatcher proto has no rule set, or contains a rule case added in a newer Envoy API than the client's protos.

Common situations: Hand-written RBAC fixtures omitting the path inside url_path; control plane using newer matcher features (e.g. new path match variants) not present in the client's envoy-type protos; malformed policy JSON from a custom xDS server.

Related errors


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