apache/pulsar · error · RestException

Unauthorized to validateBothSuperuserAndBrokerOperation for

Error message

Unauthorized to validateBothSuperuserAndBrokerOperation for originalPrincipal [${principal}] and clientAppId [${clientAppId}] about operation [${operation}] on broker [${brokerId}]

What it means

BrokersBase.validateBothSuperuserAndBrokerOperation requires the caller to pass EITHER superuser validation OR broker-operation authorization. When both fail (originalPrincipal is not a superuser and the AuthorizationService denies the broker operation), it throws HTTP 401 UNAUTHORIZED with this message listing the principal, clientAppId, operation, and brokerId.

Source

Thrown at pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/BrokersBase.java:571

                    Throwable superUserValidationException = null;
                    try {
                        superUserAccessValidation.join();
                    } catch (Throwable ex) {
                        superUserValidationException = FutureUtil.unwrapCompletionException(ex);
                    }
                    Throwable brokerOperationValidationException = null;
                    try {
                        brokerOperationValidation.join();
                    } catch (Throwable ex) {
                        brokerOperationValidationException = FutureUtil.unwrapCompletionException(ex);
                    }
                    log.debug().attr("originalPrincipal", originalPrincipal())
                            .attr("operation", operation.toString())
                            .attr("broker", brokerId)
                            .attr("superuserValidationError", superUserValidationException)
                            .attr("brokerOperationValidationError", brokerOperationValidationException)
                            .log("validateBothSuperuserAndBrokerOperation failed");
                    throw new RestException(Status.UNAUTHORIZED,
                            String.format("Unauthorized to validateBothSuperuserAndBrokerOperation for"
                                          + " originalPrincipal [%s] and clientAppId [%s] "
                                          + "about operation [%s] on broker [%s]",
                                    originalPrincipal(), clientAppId(), operation.toString(), brokerId));
                });
    }

    private CompletableFuture<Void> validateBrokerOperationAsync(String cluster, String brokerId,
                                                                 BrokerOperation operation) {
        final var pulsar = pulsar();
        if (pulsar.getBrokerService().isAuthenticationEnabled()
            && pulsar.getBrokerService().isAuthorizationEnabled()) {
            return pulsar.getBrokerService().getAuthorizationService()
                    .allowBrokerOperationAsync(cluster, brokerId, operation, originalPrincipal(),
                            clientAppId(), clientAuthData())
                    .thenAccept(isAuthorized -> {
                        if (!isAuthorized) {
                            throw new RestException(Status.UNAUTHORIZED,

View on GitHub (pinned to 820761864e)

Solutions

  1. Add the principal/role to the broker's superUserRoles (broker.conf or standalone.conf) if it should have unrestricted admin access, and restart/reload.
  2. If superuser is not appropriate, grant the role broker-operation permission in the AuthorizationService provider (e.g. allow the role the specific BrokerOperation on the cluster) so one of the two checks passes.
  3. Verify the client is authenticating as the intended role (check originalPrincipal and clientAppId in the message) — often a stale or wrong auth token is being used.
  4. Confirm authorizationEnabled and the configured authorizationProvider on the broker match your access-control setup, and that any wildcard role rules cover this principal.

Example fix

// before: broker.conf with wrong superuser role
superUserRoles=admin
// after: include the role the admin client authenticates as
superUserRoles=admin,ops-bot
Defensive patterns

Strategy: validation

Validate before calling

// verify role is a superuser before invoking broker admin ops
Set<String> superUsers = admin.brokers().getDynamicConfiguration("superUserRoles") == null
        ? Set.of() : parseRoles(admin.brokers().getDynamicConfiguration("superUserRoles"));
if (!superUsers.contains(myRole)) {
    // ensure authz provider grants the BrokerOperation, or use a superuser client
}

Try / catch

try {
    admin.brokers().getActiveBrokers(cluster);
} catch (PulsarAdminException.NotAuthorizedException e) {
    log.warn("Denied broker admin op for {} on {}", clientRole, cluster, e);
}

Prevention

When it happens

Trigger: Any of getActiveBrokers, getLeaderBroker, getOwnedNamespaces, updateDynamicConfiguration, deleteDynamicConfiguration, getAllDynamicConfigurations when: (1) authorization is enabled, (2) the original principal is not in the list of superusers, and (3) the authorization provider's allowBrokerOperationAsync returns false for the requested BrokerOperation on the target cluster/broker.

Common situations: Non-superuser operators hitting /admin/v2/brokers/configuration or dynamic-config endpoints; authorization provider misconfigured (role not granted broker-level permissions in the external authz store); token/client credentials not conveying the expected role; cluster name mismatch so the provider cannot match the broker.

Understand the failure class

Related errors


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