apache/pulsar · error · RestException

Tenant does not exist

Error message

Tenant does not exist

What it means

Thrown when the admin client's lookup of the tenant returns PulsarAdminException.NotFoundException during source registration; the worker maps this to HTTP 400 BAD_REQUEST with 'Tenant does not exist'. It means the tenant named in the request is absent from the cluster's metadata store.

Source

Thrown at pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/api/SourcesImpl.java:131

                if (namespaces != null && !namespaces.contains(qualifiedNamespaceWithCluster)) {
                    log.error().attr("tenant", tenant).attr("namespace", namespace).attr("componentName", sourceName)

                            .attr("namespace3", namespace).log("/ / Namespace does not exist");
                    throw new RestException(Response.Status.BAD_REQUEST, "Namespace does not exist");
                }
            }
        } catch (PulsarAdminException.NotAuthorizedException e) {
            log.error().attr("tenant", tenant).attr("namespace", namespace).attr("componentName", sourceName)

                    .attr("componentType", ComponentTypeUtils.toString(componentType))

                    .log("/ / Client is not authorized to operate on tenant");
            throw new RestException(Response.Status.UNAUTHORIZED, "Client is not authorized to perform operation");
        } catch (PulsarAdminException.NotFoundException e) {
            log.error().attr("tenant", tenant).attr("namespace", namespace).attr("componentName", sourceName)

                    .attr("tenant3", tenant).log("/ / Tenant does not exist");
            throw new RestException(Response.Status.BAD_REQUEST, "Tenant does not exist");
        } catch (PulsarAdminException e) {
            log.error().attr("tenant", tenant).attr("namespace", namespace).attr("componentName", sourceName)

                    .exception(e).log("/ / Issues getting tenant data");
            throw new RestException(Response.Status.INTERNAL_SERVER_ERROR, e.getMessage());
        }

        FunctionMetaDataManager functionMetaDataManager = worker().getFunctionMetaDataManager();

        if (functionMetaDataManager.containsFunction(tenant, namespace, sourceName)) {
            log.error().attr("componentType", ComponentTypeUtils.toString(componentType)).attr("tenant", tenant)

                    .attr("namespace", namespace).attr("componentName", sourceName).log("/ / already exists");
            throw new RestException(Response.Status.BAD_REQUEST,
                    String.format("%s %s already exists", ComponentTypeUtils.toString(componentType), sourceName));
        }

        FunctionDetails functionDetails = null;

View on GitHub (pinned to 820761864e)

Solutions

  1. Verify existing tenants: pulsar-admin tenants list
  2. Create the missing tenant: pulsar-admin tenants create <tenant> -r <admin-role>
  3. Create the namespace too if needed: pulsar-admin namespaces create <tenant>/<namespace>
  4. Correct the tenant field in your source configuration to an existing tenant

Example fix

// before
pulsar-admin sources create --tenant publc --namespace default ... // -> 400 Tenant does not exist
// after
pulsar-admin tenants create publc -r administrator
// or fix typo
pulsar-admin sources create --tenant public --namespace default ...
Defensive patterns

Strategy: validation

Validate before calling

try (PulsarAdmin admin = PulsarAdminClient.builder().serviceHttpUrl(adminUrl).build()) {
    if (!admin.tenants().getTenants().contains(tenant)) {
        throw new IllegalStateException("Tenant " + tenant + " does not exist; create it first");
    }
    admin.namespaces().getNamespaces(tenant); // also validates namespace
}

Try / catch

try {
    sources.createSource(sourceConfig, pkgUrl, inputStream);
} catch (PulsarAdminException e) {
    if (e.getMessage() != null && e.getMessage().contains("Tenant does not exist")) {
        admin.tenants().createTenant(tenant, new TenantInfoImpl(Collections.singleton(adminRole), Collections.singleton("standalone")));
        sources.createSource(sourceConfig, pkgUrl, inputStream);
    } else { throw e; }
}

Prevention

When it happens

Trigger: POSTing a source registration whose SourceConfig tenant field names a tenant that has not been created on the target cluster.

Common situations: Typo in the tenant name in source config YAML; deploying against a different cluster/environment than where the tenant was created; tenant deleted before redeployment; fresh cluster where bootstrap tenants were not provisioned.

Related errors


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