apache/pulsar · error · RestException
%s %s already exists
Error message
%s %s already exists
What it means
Thrown when FunctionMetaDataManager.containsFunction reports a source with the same name already exists in the tenant/namespace. The worker rejects the registration with HTTP 400 BAD_REQUEST because Pulsar treats component names as unique per namespace — you must update, not register.
Source
Thrown at pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/api/SourcesImpl.java:145
} 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;
boolean isPkgUrlProvided = isNotBlank(sourcePkgUrl);
File componentPackageFile = null;
try {
// validate parameters
try {
if (isPkgUrlProvided) {
componentPackageFile = getPackageFile(componentType, sourcePkgUrl);
functionDetails = validateUpdateRequestParams(tenant, namespace, sourceName,
sourceConfig, componentPackageFile);
} else {
if (uploadedInputStream != null) {
componentPackageFile = WorkerUtils.dumpToTmpFile(uploadedInputStream);
}View on GitHub (pinned to 820761864e)
Solutions
- Use the update endpoint/trigger instead of create: pulsar-admin sources update ...
- Delete the existing source first: pulsar-admin sources delete --tenant <t> --namespace <ns> --name <name>, then create
- List existing sources to check the collision: pulsar-admin sources list --tenant <t> --namespace <ns>
- Pick a unique sourceName for the new source
Example fix
// before pulsar-admin sources create --tenant public --namespace default --name my-source ... // -> 400 my-source already exists // after pulsar-admin sources update --tenant public --namespace default --name my-source --sourceConfigFile my-source.yaml
Defensive patterns
Strategy: validation
Validate before calling
try (PulsarAdmin admin = PulsarAdminClient.builder().serviceHttpUrl(adminUrl).build()) {
boolean exists = admin.sources().listSources(tenant, namespace)
.stream().anyMatch(s -> s.getName().equals(sourceName));
if (exists) {
admin.sources().updateSource(sourceConfig, pkgUrl, inputStream); // update instead of create
} else {
admin.sources().createSource(sourceConfig, pkgUrl, inputStream);
}
} Type guard
boolean sourceExists(java.util.List<org.apache.pulsar.common.functions.SourceConfig> configs, String name) {
return configs != null && configs.stream().anyMatch(c -> name.equals(c.getName()));
} Try / catch
try {
sources.createSource(sourceConfig, pkgUrl, inputStream);
} catch (PulsarAdminException e) {
if (e.getMessage() != null && e.getMessage().endsWith("already exists")) {
sources.updateSource(sourceConfig, pkgUrl, inputStream); // idempotent upsert
} else { throw e; }
} Prevention
- Prefer update (upsert) semantics in deployment scripts to make them idempotent
- Derive sourceName from a unique config value per environment
- List sources before create in CI to detect collisions early
- Avoid reusing one source name across teams in the same namespace
When it happens
Trigger: POSTing a registration for a source whose (tenant, namespace, sourceName) triple already has a registered source; re-running a create script without deleting the old source; accidental name collision between sources and functions in the same namespace.
Common situations: CI/CD re-deploying a source with create instead of update; failed previous deployment left the source registered; multiple teams reusing the same source name; copy-pasted configs with an unchanged sourceName.
Related errors
- %s %s already exists
- Cluster already exists
- ${duplicateBrokers} already exists in ${domainName}
- Cannot delete non empty namespace
- %s is a non-partitioned topic. Instead of calling delete-par
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/6f161d82ae83a61d.
Report an issue: GitHub.