grpc/grpc-java · error · IllegalArgumentException

Authorization policy should be a JSON object. Found: null

Error message

Authorization policy should be a JSON object. Found: null

What it means

AuthorizationPolicyTranslator.translate() parses a JSON string representing a gRPC authorization policy. JsonParser.parse() can return null (or a non-Map scalar like a string/number) when the input is not a JSON object; since a valid policy must be an object with fields like 'name' and rules, translate() throws IllegalArgumentException immediately with the actual parsed type in the message.

Source

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

          .addAllPrincipals(principals)
          .build();
      policies.put(name + "_" + policyName, policy);
    }
    return policies;
  }

  /** 
   * Translates a gRPC authorization policy in JSON string to Envoy RBAC policies.
   * On success, will return one of the following -
   * 1. One allow RBAC policy or,
   * 2. Two RBAC policies, deny policy followed by allow policy.
   * If the policy cannot be parsed or is invalid, an exception will be thrown.
   */
  public static List<RBAC> translate(String authorizationPolicy) 
            throws IllegalArgumentException, IOException {
    Object jsonObject = JsonParser.parse(authorizationPolicy);
    if (!(jsonObject instanceof Map)) {
      throw new IllegalArgumentException(
          "Authorization policy should be a JSON object. Found: "
          + (jsonObject == null ? null : jsonObject.getClass()));
    }
    @SuppressWarnings("unchecked")
    Map<String, ?> json = (Map<String, ?>)jsonObject;
    String name = JsonUtil.getString(json, "name");
    if (name == null || name.isEmpty()) {
      throw new IllegalArgumentException("\"name\" is absent or empty");
    }
    List<RBAC> rbacs = new ArrayList<>();
    List<Map<String, ?>> objects = JsonUtil.getListOfObjects(json, "deny_rules");
    if (objects != null && !objects.isEmpty()) {
      rbacs.add(
          RBAC.newBuilder()
          .setAction(Action.DENY)
          .putAllPolicies(parseRules(objects, name))
          .build());
    }

View on GitHub (pinned to 64daddc1f3)

Solutions

  1. Verify the policy string is non-empty and parses to a JSON object before calling translate: JsonParser.parse(policy) instanceof Map
  2. Check the file/env-var source actually contains the policy JSON (print it before translating)
  3. If the policy is YAML, convert it to JSON first; gRPC authz policies must be JSON objects
  4. Wrap translate() in try-catch for IllegalArgumentException and surface a clear config-loading error

Example fix

// before
List<RBAC> rbacs = AuthorizationPolicyTranslator.translate(policyJson);
// after
if (policyJson == null || policyJson.trim().isEmpty()) {
  throw new IllegalArgumentException("authorization policy file is empty");
}
List<RBAC> rbacs = AuthorizationPolicyTranslator.translate(policyJson);
Defensive patterns

Strategy: validation

Validate before calling

Object parsed = JsonParser.parse(policyJson);
if (!(parsed instanceof Map)) {
  throw new IllegalArgumentException("policy must be a JSON object, got: " + parsed);
}

Type guard

static boolean isJsonObject(String s) {
  try { return JsonParser.parse(s) instanceof Map; } catch (Exception e) { return false; }
}

Try / catch

try {
  List<RBAC> rbacs = AuthorizationPolicyTranslator.translate(policyJson);
} catch (IllegalArgumentException e) {
  log.error("Invalid authorization policy: " + e.getMessage());
  throw new ConfigException("Bad authz policy", e);
}

Prevention

When it happens

Trigger: Calling AuthorizationPolicyTranslator.translate(policy) with a policy string that parses to null, or to a JSON scalar/array instead of an object — e.g. empty string, whitespace, "null", a bare quoted string, or a JSON array.

Common situations: Config file loaded empty or not interpolated (env var unset leading to literal 'null'), reading a YAML policy that parses to a scalar, truncating the file, or passing the wrong file's contents.

Understand the failure class

Background: "Invalid JSON response" and "Failed to parse response" errors: when an API answers 200 but the body isn't the JSON your library expected — this error's family across 28 libraries.

Related errors


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