grpc/grpc-java · error · IllegalArgumentException

"key" is absent or empty

Error message

"key" is absent or empty

What it means

AuthorizationPolicyTranslator.parseHeader validates each HTTP-header rule of an authorization policy loaded from JSON. If the rule object has no "key" field, or its value is null or the empty string, the policy cannot be translated into a gRPC permission and IllegalArgumentException is thrown. The error is part of strict policy validation at translation time.

Source

Thrown at authz/src/main/java/io/grpc/authz/AuthorizationPolicyTranslator.java:77

  private static Principal parseSource(Map<String, ?> source) {
    List<String> principalsList = JsonUtil.getListOfStrings(source, "principals");
    if (principalsList == null || principalsList.isEmpty()) {
      return Principal.newBuilder().setAny(true).build();
    }
    Principal.Set.Builder principalsSet = Principal.Set.newBuilder();
    for (String principal: principalsList) {           
      principalsSet.addIds(
          Principal.newBuilder().setAuthenticated(
            Authenticated.newBuilder().setPrincipalName(
              getStringMatcher(principal)).build()).build());
    }
    return Principal.newBuilder().setOrIds(principalsSet.build()).build();
  }

  private static Permission parseHeader(Map<String, ?> header) throws IllegalArgumentException {
    String key = JsonUtil.getString(header, "key");
    if (key == null || key.isEmpty()) {
      throw new IllegalArgumentException("\"key\" is absent or empty");
    }
    if (key.charAt(0) == ':'
        || key.startsWith("grpc-")
        || UNSUPPORTED_HEADERS.contains(key.toLowerCase(Locale.ROOT))) {
      throw new IllegalArgumentException(String.format("Unsupported \"key\" %s", key));
    }
    List<String> valuesList = JsonUtil.getListOfStrings(header, "values");
    if (valuesList == null || valuesList.isEmpty()) {
      throw new IllegalArgumentException("\"values\" is absent or empty");
    }
    Permission.Set.Builder orSet = Permission.Set.newBuilder();
    for (String value: valuesList) {
      orSet.addRules(
          Permission.newBuilder().setHeader(
            HeaderMatcher.newBuilder()
            .setName(key)
            .setStringMatch(getStringMatcher(value)).build()).build());     
    }

View on GitHub (pinned to 64daddc1f3)

Solutions

  1. Add a non-empty "key" to every entry in the rule's headers list
  2. Validate the policy JSON against the authorization policy schema before loading
  3. Remove rules that have no key rather than passing empty objects
  4. Check for whitespace-only keys and trim/reject them

Example fix

// before
{"name":"allow-admin","headers":[{"values":["admin"]}]}
// after
{"name":"allow-admin","headers":[{"key":"x-user-group","values":["admin"]}]}
Defensive patterns

Strategy: validation

Validate before calling

static void checkHeaderRule(Map<String, ?> rule) {
  String key = JsonUtil.getString(rule, "key");
  if (key == null || key.isEmpty()) throw new IllegalArgumentException("header rule missing \"key\"");
}

Try / catch

try { AuthorizationPolicyTranslator.translate(policyJson, serverName); } catch (IllegalArgumentException e) { throw new PolicyValidationException("Invalid authorization policy: " + e.getMessage(), e); }

Prevention

When it happens

Trigger: Loading an authorization policy JSON where a rule's headers entry is missing "key" or has "key": "" — e.g. {"headers": [{"values": ["admin"]}]}.

Common situations: Hand-edited or generated authorization policy files missing fields; YAML/JSON templates with unfilled placeholders; upgrading gRPC and policy files written for looser validators.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


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