grpc/grpc-java · error · IllegalArgumentException

Unknown principal identifier case: " + principal.getIdentifi

Error message

Unknown principal identifier case: " + principal.getIdentifierCase()

What it means

RBAC principal protos use a oneof 'identifier' (and_ids, or_ids, not_id, authenticated, source_ip, header, url_path, metadata, etc.). parsePrincipal throws IllegalArgumentException when the identifier is unset or is a case this client version doesn't implement, since no matcher can be constructed for the principal.

Source

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

        return createSourceIpMatcher(principal.getRemoteIp());
      case SOURCE_IP: {
        // gRFC A41 has identical handling of source_ip as remote_ip and direct_remote_ip and
        // pre-dates the deprecation.
        @SuppressWarnings("deprecation")
        CidrRange sourceIp = principal.getSourceIp();
        return createSourceIpMatcher(sourceIp);
      }
      case HEADER:
        return parseHeaderMatcher(principal.getHeader());
      case NOT_ID:
        return InvertMatcher.create(parsePrincipal(principal.getNotId()));
      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) {

View on GitHub (pinned to 64daddc1f3)

Solutions

  1. Upgrade grpc-xds dependency to match the control plane's Envoy API version
  2. Ensure each Principal in the RBAC policy has an identifier set on the control plane
  3. Rewrite unsupported identifier cases using supported ones (authenticated, source_ip, header, url_path, and/or/not)
  4. Log/print the offending identifier case from the message to pinpoint the policy entry

Example fix

# before
principals: {}
# after
principals:
  - authenticated: {principal_name: {exact: "spiffe://cluster/ns/sa/sa-name"}}
Defensive patterns

Strategy: validation

Validate before calling

if (principal.getIdentifierCase() == Principal.IdentifierCase.IDENTIFIER_NOT_SET) {
  throw new IllegalArgumentException("RBAC principal must have an identifier");
}

Try / catch

try {
  Matcher m = parsePrincipal(principal);
} catch (IllegalArgumentException e) {
  logger.warning("Unsupported RBAC principal: " + e.getMessage());
  // reject the policy; do not default to allow-all
}

Prevention

When it happens

Trigger: An RBAC policy's principals list contains a Principal with IDENTIFIER_NOT_SET or a newly added Envoy identifier case unknown to the loaded protos; parsePrincipal recurses through parsePrincipalList and hits the default branch.

Common situations: Envoy control plane newer than gRPC client protos using a new principal identifier; empty principal block in a policy; custom xDS server emitting incomplete RBAC policies.

Related errors


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