apache/pulsar · error · RestException

Unauthorized to validateClusterOperation for originalPrincip

Error message

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

What it means

This 401 UNAUTHORIZED error is thrown by the broker's cluster-level authorization check. When authorization is enabled on the broker, every admin cluster operation is delegated to the AuthorizationService's allowClusterOperationAsync; if it returns false, the REST layer rejects the request with this message naming the original principal, client app id, operation, and cluster. It means the authenticated role lacks the required cluster policy permission.

Source

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

                            .log("validateBothSuperuserAndClusterPolicyOperation failed");
                    throw new RestException(Status.UNAUTHORIZED,
                            String.format("Unauthorized to validateBothSuperuserAndClusterPolicyOperation for"
                                          + " originalPrincipal [%s] and clientAppId [%s] "
                                          + "about operation [%s] on cluster [%s]",
                                    originalPrincipal(), clientAppId(), operation.toString(), clusterName));
                });
    }

    private CompletableFuture<Void> validateClusterOperationAsync(String cluster, ClusterOperation operation) {
        final var pulsar = pulsar();
        if (pulsar.getBrokerService().isAuthenticationEnabled()
            && pulsar.getBrokerService().isAuthorizationEnabled()) {
            return pulsar.getBrokerService().getAuthorizationService()
                    .allowClusterOperationAsync(cluster, operation, originalPrincipal(),
                            clientAppId(), clientAuthData())
                    .thenAccept(isAuthorized -> {
                        if (!isAuthorized) {
                            throw new RestException(Status.UNAUTHORIZED,
                                    String.format("Unauthorized to validateClusterOperation for"
                                                  + " originalPrincipal [%s] and clientAppId [%s] "
                                                  + "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())

View on GitHub (pinned to 820761864e)

Solutions

  1. Grant the principal permission for the cluster operation, e.g. via the broker authorization provider's config or a grant: pulsar-admin or the AuthorizationService grant for role + cluster + operation.
  2. If the user should be an admin, configure the role in superUserRoles in broker.conf.
  3. Verify brokerService.isAuthorizationEnabled matches your intended security posture (temporarily false for debugging only).
  4. Inspect the originalPrincipal/clientAppId in the message and confirm it is the role you intended to authenticate as (token may map to an unexpected subject).

Example fix

// before: admin role with no cluster grant gets 401
// after: grant cluster operation to the role in the authorization provider
// e.g. in AuthzProvider (or via existing grant APIs)
authorizationService.grantPermissionAsync(clusterName,
    Set.of(ClusterOperation.GET), role, null);
// or broker.conf
superUserRoles=my-admin-role
Defensive patterns

Strategy: validation

Validate before calling

// before the call, check the role has the grant (using the admin API)
Set<String> perms = admin.clusters().getClusterPermission(cluster); // or your provider's lookup
if (!perms.contains(role)) { /* grant or use a superuser role first */ }

Try / catch

try { admin.clusters().getCluster(cluster); }
catch (PulsarAdminException e) {
  if (e.getStatusCode() == 401) {
    log.error("Not authorized for cluster op as {}", e.getMessage());
  } else throw e;
}

Prevention

When it happens

Trigger: Calling any admin cluster REST endpoint (e.g. GET/PUT /admin/v3/clusters/{cluster}) with authorizationEnabled=true while the role has no cluster grant; the role was authenticated successfully but not authorized for the specific cluster operation.

Common situations: Missing or stale authorization provider configuration; admin client using a token/role that was never granted cluster access; wildcard or role grants misconfigured in the authorization provider; after rotating credentials the new role lacks grants.

Understand the failure class

Related errors


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