apache/pulsar · error · RestException
Clusters do not exist
Error message
Clusters do not exist
What it means
HTTP 412 PRECONDITION_FAILED raised by validateClustersAsync when a tenant creation/update request lists clusters that do not exist in the broker's cluster registry. The broker compares requested allowedClusters against availableClusters and rejects if any are missing.
Source
Thrown at pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/TenantsBase.java:323
Set<String> cleanedClusters = allowedClusters.stream()
.filter(c -> !StringUtils.isBlank(c))
.collect(Collectors.toSet());
if (cleanedClusters.isEmpty() || allowedClusters.stream().anyMatch(StringUtils::isBlank)) {
log.warn("Validation failed: allowed clusters are empty or contain blanks");
return FutureUtil.failedFuture(
new RestException(Status.PRECONDITION_FAILED, "Clusters cannot be empty or blank"));
}
return clusterResources().listAsync().thenAccept(availableClusters -> {
List<String> nonexistentClusters = allowedClusters.stream()
.filter(cluster -> !availableClusters.contains(cluster))
.collect(Collectors.toList());
if (nonexistentClusters.size() > 0) {
log.warn()
.attr("clusters", nonexistentClusters)
.log("Failed to validate due to clusters do not exist");
throw new RestException(Status.PRECONDITION_FAILED, "Clusters do not exist");
}
});
}
private CompletableFuture<Void> validateAdminRoleAsync(TenantInfoImpl info) {
if (info.getAdminRoles() != null && !info.getAdminRoles().isEmpty()) {
for (String adminRole : info.getAdminRoles()) {
if (!StringUtils.trim(adminRole).equals(adminRole)) {
log.warn()
.attr("adminRole", adminRole)
.log("Failed to validate due to adminRole contains whitespace in the beginning or end.");
return FutureUtil.failedFuture(new RestException(Status.PRECONDITION_FAILED,
"AdminRoles contains whitespace in the beginning or end."));
}
}
}
return CompletableFuture.completedFuture(null);
}View on GitHub (pinned to 820761864e)
Solutions
- Register the missing cluster: PUT /admin/v2/clusters/{cluster} with its service URL, or remove it from the tenant's allowedClusters.
- Verify existing clusters with GET /admin/v2/clusters and correct any typos in the request body.
- If migrating configs, update tenant bodies to only reference clusters present in the target installation.
- Retry after cluster provisioning completes if clusters are created by automation concurrently.
Example fix
// before
TenantInfo info = TenantInfo.builder()
.adminRoles(Set.of("admin"))
.allowedClusters(Set.of("cluster-a", "cluster-b")) // cluster-b not registered
.build();
// after
Set<String> available = admin.clusters().getClusters();
TenantInfo info = TenantInfo.builder()
.adminRoles(Set.of("admin"))
.allowedClusters(Sets.intersection(Set.of("cluster-a", "cluster-b"), new HashSet<>(available)))
.build(); Defensive patterns
Strategy: validation
Validate before calling
Set<String> available = new HashSet<>(admin.clusters().getClusters());
Set<String> requested = tenantInfo.getAllowedClusters();
if (!available.containsAll(requested)) {
Set<String> missing = new HashSet<>(requested);
missing.removeAll(available);
throw new IllegalArgumentException("Clusters do not exist: " + missing);
} Try / catch
try {
admin.tenants().createTenant(tenant, info);
} catch (PulsarAdminException e) {
if (e.getStatusCode() == 412 && e.getMessage().contains("Clusters do not exist")) {
// correct allowedClusters against admin.clusters().getClusters() and retry
}
} Prevention
- Diff allowedClusters against GET /admin/v2/clusters before every tenant create/update.
- Register all replication target clusters before referencing them in tenants.
- Automate cluster onboarding so tenant configs never reference absent clusters.
- Watch for typos and case mismatches in cluster names.
When it happens
Trigger: PUT/POST /admin/v2/tenants/{tenant} whose TenantInfo.allowedClusters (or clusters in the JSON body) contains cluster names not registered via PUT /admin/v2/clusters/{cluster}.
Common situations: Typo in cluster name; copying tenant config from another Pulsar installation; cluster deregistered or not yet provisioned; case-sensitivity mismatches; cross-cluster replication setups where the peer cluster was never onboarded.
Related errors
- cluster data is required
- Invalid cluster id: ${clusterId}
- Tenant name or namespace is not valid
- Peer cluster ${peerCluster} does not exist
- Cluster ${cluster} does not exist.
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/5844172ad9b5e589.
Report an issue: GitHub.