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
- Grant the policy operation: admin.namespaces().grantPermissionOnNamespace or use grantPermissionOnSubscription/PoliciesOperation grants per your authorization provider
- Update automation/service accounts to include the required PoliciesOperation for the policies they manage
- Verify which policy is being denied from the message's policy field and check getPermissions output
- 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
- Map each automation job to the exact PoliciesOperation it needs
- Re-run grant audits after upgrading brokers with per-policy authorization
- Keep policy grants separate from general namespace grants
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
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- Unauthorized to validateNamespaceOperation for operation [%s
- Cluster [%s] is not in the list of allowed clusters list for
- Unauthorized to validateTenantOperation for originalPrincipa
- Invalid broker configuration. Authentication must be enabled
- Broker is forbidden to do read-write operations
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/92a77fe21f75a260.
Report an issue: GitHub.