apache/pulsar · error · RestException
Tenant not found
Error message
Tenant not found
What it means
A 404 NOT_FOUND thrown by the namespace listing flow when the tenant referenced in the request does not exist. After validating the tenant operation (LIST_NAMESPACES) and checking tenant existence via tenantResources().tenantExistsAsync, a missing tenant produces this error.
Source
Thrown at pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/NamespacesBase.java:148
protected CompletableFuture<List<String>> internalGetTenantNamespaces(String tenant) {
if (tenant == null) {
return FutureUtil.failedFuture(new RestException(Status.BAD_REQUEST, "Tenant should not be null"));
}
try {
NamedEntity.checkName(tenant);
} catch (IllegalArgumentException e) {
log.warn()
.attr("tenant", tenant)
.exception(e)
.log("Tenant name is invalid");
return FutureUtil.failedFuture(new RestException(Status.PRECONDITION_FAILED, "Tenant name is not valid"));
}
return validateTenantOperationAsync(tenant, TenantOperation.LIST_NAMESPACES)
.thenCompose(__ -> tenantResources().tenantExistsAsync(tenant))
.thenCompose(existed -> {
if (!existed) {
throw new RestException(Status.NOT_FOUND, "Tenant not found");
}
return tenantResources().getListOfNamespacesAsync(tenant);
});
}
protected CompletableFuture<Void> internalCreateNamespace(Policies policies) {
return validateTenantOperationAsync(namespaceName.getTenant(), TenantOperation.CREATE_NAMESPACE)
.thenCompose(__ -> validatePoliciesReadOnlyAccessAsync())
.thenCompose(__ -> validatePoliciesAsync(namespaceName, policies))
.thenCompose(__ -> {
int maxNamespacesPerTenant = pulsar().getConfiguration().getMaxNamespacesPerTenant();
// no distributed locks are added here.In a concurrent scenario, the threshold will be exceeded.
if (maxNamespacesPerTenant > 0) {
return tenantResources().getListOfNamespacesAsync(namespaceName.getTenant())
.thenAccept(namespaces -> {
if (namespaces != null && namespaces.size() > maxNamespacesPerTenant) {
throw new RestException(Status.PRECONDITION_FAILED,
"Exceed the maximum number of namespace in tenant :"View on GitHub (pinned to 820761864e)
Solutions
- Confirm the tenant exists: GET /admin/v3/tenants (or pulsar-admin tenants list) and use an exact existing tenant name.
- Create the tenant if missing: pulsar-admin tenants create <tenant> with admin roles and allowed clusters.
- Check which cluster the request targets — the tenant may exist on a different cluster.
Example fix
// before
admin.namespaces().getNamespaces("my-tennat"); // 404
// after
if (admin.tenants().getTenants().contains("mytenant")) {
admin.namespaces().getNamespaces("mytenant");
} Defensive patterns
Strategy: try-catch
Validate before calling
if (!admin.tenants().getTenants().contains(tenant)) {
throw new IllegalStateException("tenant " + tenant + " does not exist on this cluster");
} Try / catch
try { admin.namespaces().getNamespaces(tenant); }
catch (PulsarAdminException e) {
if (e.getStatusCode() == 404 && e.getMessage().contains("Tenant not found")) {
admin.tenants().createTenant(tenant, ...);
} else throw e;
} Prevention
- Validate tenant names against the tenants list before namespace operations
- Watch for typos/case mismatches in tenant names
- Re-check config after tenant deletions
- Point clients at the correct cluster where the tenant exists
When it happens
Trigger: GET /admin/v3/namespaces/{tenant} where the tenant was deleted, never created, or the name is mistyped (case-sensitivity/typo) on a cluster where it doesn't exist.
Common situations: Stale configuration in clients pointing at a removed tenant; multi-cluster setups where the tenant exists only on another cluster; typos like 'my-tennat'; tenant deletion racing with namespace list calls.
Related errors
- Namespace does not exist
- Message not found
- Tenant does not exist
- Tenant does not exist
- NamespaceIsolationPolicies for cluster ${cluster} does not e
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/ff26eb7b8bbe98d4.
Report an issue: GitHub.