apache/pulsar · error · RestException
Invalid cluster id: ${clusterId}
Error message
Invalid cluster id: ${clusterId} What it means
HTTP 403 (FORBIDDEN) returned by the set-replication-clusters API when one of the requested clusterIds is not a cluster registered in this Pulsar instance (clustersAsync() does not contain it). The API refuses to point a namespace at an unknown cluster.
Source
Thrown at pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/NamespacesBase.java:865
.thenApply(policies -> policies.replication_clusters);
}
@SuppressWarnings("checkstyle:WhitespaceAfter")
protected CompletableFuture<Void> internalSetNamespaceReplicationClusters(List<String> clusterIds,
boolean compareTopicPartitions) {
return validateNamespacePolicyOperationAsync(namespaceName, PolicyName.REPLICATION, PolicyOperation.WRITE)
.thenCompose(__ -> validatePoliciesReadOnlyAccessAsync())
.thenApply(__ -> {
if (CollectionUtils.isEmpty(clusterIds)) {
throw new RestException(Status.PRECONDITION_FAILED, "ClusterIds should not be null or empty");
}
return Sets.newHashSet(clusterIds);
}).thenCompose(replicationClusterSet -> clustersAsync()
.thenCompose(clusters -> {
List<CompletableFuture<Void>> futures =
replicationClusterSet.stream().map(clusterId -> {
if (!clusters.contains(clusterId)) {
throw new RestException(Status.FORBIDDEN,
"Invalid cluster id: " + clusterId);
}
return validatePeerClusterConflictAsync(clusterId, replicationClusterSet)
.thenCompose(__ -> getNamespacePoliciesAsync(this.namespaceName)
.thenCompose(nsPolicies -> {
if (!Policies.checkNewReplicationClusters(nsPolicies,
replicationClusterSet)) {
String msg = String.format("Cluster [%s] is not in the "
+ "list of allowed clusters list for namespace "
+ "[%s]", clusterId, namespaceName.toString());
log.info(msg);
throw new RestException(Status.BAD_REQUEST, msg);
}
return validateClusterForTenantAsync(
namespaceName.getTenant(), clusterId);
}));
}).collect(Collectors.toList());
return FutureUtil.waitForAll(futures).thenApply(__ -> replicationClusterSet);View on GitHub (pinned to 820761864e)
Solutions
- List registered clusters with GET /admin/v2/clusters and use exactly those names.
- Create the missing cluster via PUT /admin/v2/clusters/{clusterId} if it should exist.
- Fix typos/case mismatches in the clusterIds list.
- Remove stale cluster ids from your replication configuration templates.
Example fix
// before
setReplicationClusters(ns, List.of("cluster-a", "cluster-b")); // cluster-b not registered
// after
Set<String> known = admin.clusters().getClusters();
List<String> valid = clusterIds.stream().filter(known::contains).toList();
setReplicationClusters(ns, valid); Defensive patterns
Strategy: validation
Validate before calling
Set<String> registered = new HashSet<>(admin.clusters().getClusters());
List<String> invalid = clusterIds.stream().filter(c -> !registered.contains(c)).toList();
if (!invalid.isEmpty()) throw new IllegalArgumentException("Unknown clusters: " + invalid); Try / catch
try {
admin.namespaces().setNamespaceReplicationClusters(ns, clusterIds);
} catch (PulsarAdminException.NotAllowedException e) {
log.error("Invalid cluster id in replication set: {}", clusterIds);
} Prevention
- Fetch GET /admin/v2/clusters and validate ids before submitting
- Keep cluster names in a shared, versioned config rather than free text
- Watch for cluster deletions and update referencing namespaces
- Mind case sensitivity and typos in cluster ids
When it happens
Trigger: POST /namespaces/{tenant}/{namespace}/replication containing a cluster id that was never created, was deleted, or is misspelled; the check is `!clusters.contains(clusterId)` inside internalSetNamespaceReplicationClusters.
Common situations: Config drift between environments (cluster exists in staging, not in prod); typo like 'cluster-a-west' vs 'cluster-a'; replication config copied from another Pulsar installation; cluster removed by another admin while replication config still references it.
Related errors
- ClusterIds should not be null or empty
- Cluster [${clusterId}] is not in the list of allowed cluster
- cluster data is required
- Peer cluster ${peerCluster} does not exist
- Clusters do not exist
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/bc94a0214c36b679.
Report an issue: GitHub.