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
- Create the policy grant for the role: allow ClusterPolicyOperation for the specific policyName and cluster in your authorization provider.
- Elevate the role to superUserRoles if it is meant to manage all policies.
- Check the authorization provider logs/implementation to confirm allowClusterPolicyOperationAsync is wired correctly (custom providers may default to false).
- 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
- Grant specific ClusterPolicyOperations per role, not just cluster-level grants
- Confirm custom AuthorizationProviders implement allowClusterPolicyOperationAsync rather than defaulting to false
- Verify cluster name in the grant matches the request
- Test policy operations with a dedicated non-superuser role in staging
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
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- Unauthorized to validateClusterOperation for originalPrincip
- Cluster [${clusterId}] is not in the list of allowed cluster
- Tenant not found
- Exceed the maximum number of namespace in tenant :${tenant}
- Concurrent modification
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/c34eb5f27b1d7a4f.
Report an issue: GitHub.