grpc/grpc-java · error · IllegalArgumentException

Failed to translate authorization policy

Error message

Failed to translate authorization policy

What it means

AuthorizationServerInterceptor's private constructor calls AuthorizationPolicyTranslator.translate(policy) and validates the returned RBAC list. A valid translation yields 1 RBAC (allow-only policy) or 2 RBACs (deny + allow). If translate() returns null, empty, or more than 2 entries, the constructor throws IllegalArgumentException indicating the policy failed to translate — a sanity guard against an unexpected translator output.

Source

Thrown at authz/src/main/java/io/grpc/authz/AuthorizationServerInterceptor.java:49

import java.util.List;

/**
 * Authorization server interceptor for static policy. The class will get
 * <a href="https://github.com/grpc/proposal/blob/master/A43-grpc-authorization-api.md#user-facing-authorization-policy">
 * gRPC Authorization policy</a> as a JSON string during initialization.
 * This policy will be translated to Envoy RBAC policies to make
 * authorization decisions. The policy cannot be changed once created. To
 * change the policy after creation, see FileWatcherAuthorizationServerInterceptor.
 */
@ExperimentalApi("https://github.com/grpc/grpc-java/issues/9746")
public final class AuthorizationServerInterceptor implements ServerInterceptor {
  private final List<ServerInterceptor> interceptors = new ArrayList<>();

  private AuthorizationServerInterceptor(String authorizationPolicy) 
      throws IOException {
    List<RBAC> rbacs = AuthorizationPolicyTranslator.translate(authorizationPolicy);
    if (rbacs == null || rbacs.isEmpty() || rbacs.size() > 2) {
      throw new IllegalArgumentException("Failed to translate authorization policy");
    }
    for (RBAC rbac: rbacs) {
      interceptors.add(
          InternalRbacFilter.createInterceptor(
            io.envoyproxy.envoy.extensions.filters.http.rbac.v3.RBAC.newBuilder()
            .setRules(rbac).build()));
    }
  }

  @Override
  public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(
      ServerCall<ReqT, RespT> call, Metadata headers, 
      ServerCallHandler<ReqT, RespT> next) {
    for (ServerInterceptor interceptor: interceptors) {
      next = InternalServerInterceptors.interceptCallHandlerCreate(interceptor, next);
    }
    return next.startCall(call, headers);
  }

View on GitHub (pinned to 64daddc1f3)

Solutions

  1. Pass a well-formed authorization policy JSON object with "name" and "allow_rules" (plus optional "deny_rules")
  2. Test the same string against AuthorizationPolicyTranslator.translate() first to see the precise validation failure
  3. Ensure the policy follows the documented gRPC authz policy v1 schema

Example fix

// before
ServerInterceptor i = AuthorizationServerInterceptor.create("{}");
// after
ServerInterceptor i = AuthorizationServerInterceptor.create(
    "{\"name\": \"p\", \"allow_rules\": []}");
Defensive patterns

Strategy: validation

Validate before calling

List<RBAC> rbacs = AuthorizationPolicyTranslator.translate(policyJson);
if (rbacs == null || rbacs.isEmpty() || rbacs.size() > 2) {
  throw new IllegalArgumentException("policy translates to invalid RBAC set");
}

Try / catch

try {
  ServerInterceptor i = AuthorizationServerInterceptor.create(policyJson);
} catch (IOException | IllegalArgumentException e) {
  throw new IllegalStateException("Cannot initialize authz interceptor: " + e.getMessage(), e);
}

Prevention

When it happens

Trigger: Constructing AuthorizationServerInterceptor via its factory methods with an authorization policy string that translate() rejects or produces an out-of-contract result for (null/empty/>2 RBACs). Typically reached through a policy string that passes initial JSON checks but yields an invalid structure.

Common situations: Passing a non-policy JSON object (e.g. a config object without rules) to the interceptor factory; a mismatch between library versions where the policy schema changed.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — 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/851a9c47038c8fdf. Report an issue: GitHub.