apache/pulsar · error · RestException

Unauthorized to validateClusterPolicyOperation for originalP

Error message

Unauthorized to validateClusterPolicyOperation for originalPrincipal [${principal}] and clientAppId [${clientAppId}] about operation [${operation}] on cluster [${cluster}]

What it means

This 401 UNAUTHORIZED error is thrown when the cluster-policy-level authorization check fails. For operations on a named cluster policy (e.g. namespace-level policies applied at cluster scope), the broker calls AuthorizationService.allowClusterPolicyOperationAsync; a false result produces this RestException. It identifies the original principal, client app id, policy operation, and cluster.

Source

Thrown at pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/ClustersBase.java:1327

                                                  + "about operation [%s] on cluster [%s]",
                                            originalPrincipal(), clientAppId(), operation.toString(), cluster));
                        }
                    });
        }
        return CompletableFuture.completedFuture(null);
    }

    private CompletableFuture<Void> validateClusterPolicyOperationAsync(String cluster, PolicyName policyName,
                                                                        PolicyOperation operation) {
        final var pulsar = pulsar();
        if (pulsar.getBrokerService().isAuthenticationEnabled()
            && pulsar.getBrokerService().isAuthorizationEnabled()) {
            return pulsar.getBrokerService().getAuthorizationService()
                    .allowClusterPolicyOperationAsync(cluster, policyName, operation, originalPrincipal(),
                            clientAppId(), clientAuthData())
                    .thenAccept(isAuthorized -> {
                        if (!isAuthorized) {
                            throw new RestException(Status.UNAUTHORIZED,
                                    String.format("Unauthorized to validateClusterPolicyOperation for"
                                                  + " originalPrincipal [%s] and clientAppId [%s] "
                                                  + "about operation [%s] on cluster [%s]",
                                            originalPrincipal(), clientAppId(), operation.toString(), cluster));
                        }
                    });
        }
        return CompletableFuture.completedFuture(null);
    }
}

View on GitHub (pinned to 820761864e)

Solutions

  1. Create the policy grant for the role: allow ClusterPolicyOperation for the specific policyName and cluster in your authorization provider.
  2. Elevate the role to superUserRoles if it is meant to manage all policies.
  3. Check the authorization provider logs/implementation to confirm allowClusterPolicyOperationAsync is wired correctly (custom providers may default to false).
  4. Verify the cluster name in the request matches the cluster where the grant exists.

Example fix

// before: role not granted -> 401
// after: grant policy operation in custom AuthorizationProvider
@Override
public boolean allowClusterPolicyOperation(String cluster, String policyName,
    PolicyOperation operation, String role, AuthenticationDataSource authData) {
    return policyGrants.getOrDefault(role, Set.of())
        .contains(cluster + ":" + policyName + ":" + operation);
}
Defensive patterns

Strategy: validation

Validate before calling

// verify policy grants exist before invoking policy operations
if (!policyGrants.containsKey(role)) { /* create grant for policyName/operation */ }

Try / catch

try { admin.clusters().updateClusterPolicyOperation(...); }
catch (PulsarAdminException e) {
  if (e.getStatusCode() == 401) { /* add the missing policy grant */ }
  else throw e;
}

Prevention

When it happens

Trigger: Invoking admin endpoints that validate cluster policy operations (validateClusterPolicyOperationAsync path) while authorizationEnabled=true and the role has no grant for the given policyName/operation on the cluster.

Common situations: Authorization provider lacks policy-level grant support or the grant for that specific policy name was never created; using a read-only role for a policy mutation (PUT/POST); grant recorded for a different cluster name.

Understand the failure class

Related errors


AI-assisted analysis of apache/pulsar@820761864e (2026-09-06). Data as JSON: /api/errors/c34eb5f27b1d7a4f. Report an issue: GitHub.