apache/pulsar · error · RestException
Cannot delete the global namespace ${nsName}. There are stil
Error message
Cannot delete the global namespace ${nsName}. There are still more than one replication clusters configured or replication clusters is empty. What it means
A 412 PRECONDITION_FAILED thrown when deleting a global namespace whose policies still resolve to more than one replication cluster, or to an empty replication cluster set — policies.getClusterThatCanDeleteNamespace() returns null in both cases. The broker only allows deleting a global namespace when exactly one replication cluster remains and it is safe to proceed.
Source
Thrown at pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/NamespacesBase.java:494
validateTenantOperationAsync(nsName.getTenant(), TenantOperation.DELETE_NAMESPACE)
.thenCompose(__ -> validatePoliciesReadOnlyAccessAsync())
.thenCompose(__ -> {
if (force && !pulsar().getConfiguration().isForceDeleteNamespaceAllowed()) {
throw new RestException(Status.METHOD_NOT_ALLOWED,
"Broker doesn't allow forced deletion of namespaces");
}
return CompletableFuture.completedFuture(null);
})
.thenCompose(__ -> namespaceResources().getPoliciesAsync(nsName))
.thenCompose(policiesOpt -> {
if (policiesOpt.isEmpty()) {
throw new RestException(Status.NOT_FOUND, "Namespace " + nsName + " does not exist.");
}
Policies policies = policiesOpt.get();
String cluster = policies.getClusterThatCanDeleteNamespace();
if (cluster == null) {
// There are still more than one clusters configured for the global namespace
throw new RestException(Status.PRECONDITION_FAILED,
"Cannot delete the global namespace " + nsName + ". There are still more than "
+ "one replication clusters configured or replication clusters is empty.");
}
if (!cluster.equals(config().getClusterName())) {
// the only replication cluster is other cluster, redirect
return clusterResources().getClusterAsync(cluster)
.thenCompose(replClusterDataOpt -> {
ClusterData replClusterData = replClusterDataOpt
.orElseThrow(() -> new RestException(Status.NOT_FOUND,
"Cluster " + cluster + " does not exist"));
URL replClusterUrl;
try {
if (!replClusterData.isBrokerClientTlsEnabled()) {
replClusterUrl = new URL(replClusterData.getServiceUrl());
} else if (StringUtils.isNotBlank(replClusterData.getServiceUrlTls())) {
replClusterUrl = new URL(replClusterData.getServiceUrlTls());
} else {
throw new RestException(Status.PRECONDITION_FAILED,View on GitHub (pinned to 820761864e)
Solutions
- Reduce replication clusters to exactly one first: POST /admin/v2/namespaces/{tenant}/{namespace}/replication with a single-cluster body, then delete the namespace.
- If clusters are drained intentionally, ensure the remaining single cluster matches the broker you call, otherwise expect a redirect (error 94/97 path).
- Do not set the replication list to empty to 'prepare' for deletion — that also triggers this error; remove namespaces per cluster instead.
- Check the effective policies via GET /admin/v2/namespaces/{tenant}/{namespace}/replication to confirm current cluster set.
Example fix
// before curl -X POST http://broker:8080/admin/v2/namespaces/t/ns/replication -d '[]' curl -X DELETE http://broker:8080/admin/v2/namespaces/t/ns // 412 // after curl -X POST http://broker:8080/admin/v2/namespaces/t/ns/replication -d '["us-west"]' curl -X DELETE http://broker:8080/admin/v2/namespaces/t/ns
Defensive patterns
Strategy: validation
Validate before calling
const clusters = await admin.namespaces().getNamespaceReplicationClusters(tenant, ns);
if (clusters.length !== 1) {
throw new Error(`reduce replication clusters to exactly one before delete, got: ${clusters}`);
} Try / catch
try {
await admin.namespaces().deleteNamespace(tenant, ns);
} catch (e) {
if (e.getStatusCode() === 412) {
await admin.namespaces().setNamespaceReplicationClusters(tenant, ns, ['local']);
await admin.namespaces().deleteNamespace(tenant, ns);
} else throw e;
} Prevention
- Always narrow replication_clusters to one before deleting global namespaces
- Never set replication list to empty as a 'pre-delete' step
- Check policies with GET .../replication before delete in scripts
When it happens
Trigger: DELETE /admin/v2/namespaces/{tenant}/{namespace} where the namespace policy's replication_clusters still contains 2+ clusters, or where replication_clusters is empty, so no single owning cluster can be determined.
Common situations: Geo-replicated namespaces where replication was never narrowed down before deletion; automation that unsets replication clusters to empty instead of reducing to one; operators unaware global namespaces must be drained cluster-by-cluster.
Related errors
- Cannot delete the global namespace ${namespaceName}. There a
- Cannot delete non empty namespace
- Broker doesn't allow forced deletion of namespaces
- The replication cluster does not provide TLS encrypted servi
- Local cluster is not part of replicate cluster list
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/f9d7a61da6d92c09.
Report an issue: GitHub.