apache/pulsar · warning · RestException

Unauthorized to validateNamespacePolicyOperation for operati

Error message

Unauthorized to validateNamespacePolicyOperation for operation [%s] on namespace [%s] on policy [%s]

What it means

HTTP 403 FORBIDDEN thrown by validateNamespacePolicyOperationAsync: the authorization service denied the requested policy-level operation on the namespace (e.g. modifying retention, backlog quota, replication, or auto-creation policies). Policy operations are checked separately from generic namespace operations so finer-grained policy RBAC can be enforced.

Source

Thrown at pulsar-broker/src/main/java/org/apache/pulsar/broker/web/PulsarWebResource.java:1058

        sync(()-> validateNamespacePolicyOperationAsync(namespaceName, policy, operation));
    }

    public CompletableFuture<Void> validateNamespacePolicyOperationAsync(NamespaceName namespaceName,
                                                 PolicyName policy,
                                                 PolicyOperation operation) {
        if (pulsar().getConfiguration().isAuthenticationEnabled()
                && pulsar().getBrokerService().isAuthorizationEnabled()) {
            if (!isClientAuthenticated(clientAppId())) {
                return FutureUtil.failedFuture(
                        new RestException(Status.FORBIDDEN, "Need to authenticate to perform the request"));
            }

            return pulsar().getBrokerService().getAuthorizationService()
                    .allowNamespacePolicyOperationAsync(namespaceName, policy, operation,
                            originalPrincipal(), clientAppId(), clientAuthData())
                    .thenAccept(isAuthorized -> {
                        if (!isAuthorized) {
                            throw new RestException(Status.FORBIDDEN,
                                    String.format("Unauthorized to validateNamespacePolicyOperation for"
                                                    + " operation [%s] on namespace [%s] on policy [%s]",
                                            operation.toString(), namespaceName, policy.toString()));
                        }
                    });
        }
        return CompletableFuture.completedFuture(null);
    }

    protected CompletableFuture<Void> canUpdateCluster(String tenant, Set<String> oldClusters,
            Set<String> newClusters) {
        // Check if any clusters are being removed
        Set<String> removedClusters = new java.util.HashSet<>(oldClusters);
        removedClusters.removeAll(newClusters);
        if (removedClusters.isEmpty()) {
            return CompletableFuture.completedFuture(null);
        }

View on GitHub (pinned to 820761864e)

Solutions

  1. Grant the policy operation: admin.namespaces().grantPermissionOnNamespace or use grantPermissionOnSubscription/PoliciesOperation grants per your authorization provider
  2. Update automation/service accounts to include the required PoliciesOperation for the policies they manage
  3. Verify which policy is being denied from the message's policy field and check getPermissions output
  4. If the broker upgraded to per-policy checks, re-audit role grants against the new operation taxonomy

Example fix

// before: denied updating retention policy
admin.namespaces().setRetention("public/default", new RetentionPolicies(7, 1024));
// after: ensure role has the retention policy grant per configured AuthorizationService
admin.namespaces().grantPermissionOnNamespace("public/default", "data-eng-role",
    EnumSet.of(PoliciesOperation.SET_RETENTION));
Defensive patterns

Strategy: validation

Validate before calling

Set<String> grants = admin.namespaces().getPermissions(ns).getOrDefault(myRole, Set.of());
// confirm the role covers the specific policy operation before mutating policies

Try / catch

try {
    policyOp(ns);
} catch (PulsarAdminException e) {
    if (e.getStatusCode() == 403 && e.getMessage().contains("validateNamespacePolicyOperation")) {
        throw new SecurityException("grant the PoliciesOperation for " + policy, e);
    } else throw e;
}

Prevention

When it happens

Trigger: Any admin API that mutates or reads a specific namespace policy (retention, persistence, deduplication, offload, backlog quotas, etc.) where allowNamespacePolicyOperationAsync returns false for the role/policy pair.

Common situations: Role has general namespace grants but not the specific policy operation; security hardening introduced per-policy authorization (AuthorizationService.allowNamespacePolicyOperationAsync) and legacy grants no longer suffice; automation accounts missing the new policy action.

Understand the failure class

Related errors


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