apache/pulsar · error · RestException

Cluster [%s] is not in the list of allowed clusters list for

Error message

Cluster [%s] is not in the list of allowed clusters list for tenant [%s]

What it means

Each Pulsar tenant has an allowedClusters list. validateClusterForTenant checks that the cluster the operation targets (e.g. where a namespace is being created) is in that tenant's allowedClusters and throws 403 FORBIDDEN otherwise. It is a tenant-scoped cluster allowlist check, not a generic auth failure.

Source

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

    protected void validateClusterForTenant(String tenant, String cluster) {
        TenantInfo tenantInfo;
        try {
            tenantInfo = pulsar().getPulsarResources().getTenantResources().getTenant(tenant)
                    .orElseThrow(() -> new RestException(Status.NOT_FOUND, "Tenant does not exist"));
        } catch (RestException e) {
            log.warn().attr("tenant", tenant).log("Failed to get tenant admin data for tenant");
            throw e;
        } catch (Exception e) {
            log.error().attr("tenant", tenant).exception(e).log("Failed to get tenant admin data for tenant");
            throw new RestException(e);
        }

        // Check if tenant is allowed on the cluster
        if (!tenantInfo.getAllowedClusters().contains(cluster)) {
            String msg = String.format("Cluster [%s] is not in the list of allowed clusters list for tenant [%s]",
                    cluster, tenant);
            log.info(msg);
            throw new RestException(Status.FORBIDDEN, msg);
        }
        log.info().attr("tenant", tenant).log("Successfully validated clusters on tenant");
    }

    protected CompletableFuture<Void> validateClusterForTenantAsync(String tenant, String cluster) {
        return pulsar().getPulsarResources().getTenantResources().getTenantAsync(tenant)
                .thenAccept(tenantInfo -> {
                    if (tenantInfo.isEmpty()) {
                        throw new RestException(Status.NOT_FOUND, "Tenant does not exist");
                    }
                    if (!tenantInfo.get().getAllowedClusters().contains(cluster)) {
                        String msg = String.format("Cluster [%s] is not in the list of allowed clusters list"
                                        + " for tenant [%s]", cluster, tenant);
                        log.info(msg);
                        throw new RestException(Status.FORBIDDEN, msg);
                    }
                });
    }

View on GitHub (pinned to 820761864e)

Solutions

  1. Add the cluster to the tenant's allowed clusters: pulsar-admin tenants update <tenant> --allowed-clusters <c1,c2,...>
  2. If the cluster shouldn't be used, retry the operation against a cluster already in the tenant's allowedClusters
  3. Check the tenant's current config: pulsar-admin tenants get <tenant> and compare allowedClusters to the cluster in the failing request

Example fix

// before
pulsar-admin tenants create my-tenant --allowed-clusters cluster-a
// after (allow cluster-b too)
pulsar-admin tenants update my-tenant --allowed-clusters cluster-a,cluster-b
Defensive patterns

Strategy: validation

Validate before calling

// Ensure the target cluster is in the tenant's allowedClusters before the operation
Set<String> allowed = admin.tenants().getTenant(tenant).getAllowedClusters();
if (!allowed.contains(targetCluster)) {
    admin.tenants().updateTenant(tenant,
        new TenantInfoImpl(tenant.getAdminRoles(), append(allowed, targetCluster)));
}

Prevention

When it happens

Trigger: Creating/updating a namespace or namespace-isolated policy under tenant T with cluster C where T's TenantInfo.allowedClusters does not contain C. Also hit when passing --cluster to namespace/tenant admin operations against a cluster the tenant was never provisioned on.

Common situations: Tenant created with default allowedClusters but admins operate against a new/renamed cluster; cluster renamed or added after tenant creation; multi-cluster setups where geo-replication clusters weren't added to the tenant; pointing pulsar-admin (service URL) at a different cluster than the tenant covers.

Related errors


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