{"record":{"id":"2f90bde2255a1de3","repo":"apache/pulsar","slug":"s-s-already-exists-2f90bd","errorCode":null,"errorMessage":"%s %s already exists","messagePattern":"(.+?) (.+?) already exists","errorType":"http","errorClass":"RestException","httpStatus":400,"severity":"error","filePath":"pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/api/SinksImpl.java","lineNumber":146,"sourceCode":"        } catch (PulsarAdminException.NotFoundException e) {\n            log.error().attr(\"tenant\", tenant).attr(\"namespace\", namespace).attr(\"componentName\", sinkName)\n\n                    .attr(\"tenant3\", tenant).log(\"/ / Tenant does not exist\");\n            throw new RestException(Response.Status.BAD_REQUEST, \"Tenant does not exist\");\n        } catch (PulsarAdminException e) {\n            log.error().attr(\"tenant\", tenant).attr(\"namespace\", namespace).attr(\"componentName\", sinkName)\n\n                    .exception(e).log(\"/ / Issues getting tenant data\");\n            throw new RestException(Response.Status.INTERNAL_SERVER_ERROR, e.getMessage());\n        }\n\n        FunctionMetaDataManager functionMetaDataManager = worker().getFunctionMetaDataManager();\n\n        if (functionMetaDataManager.containsFunction(tenant, namespace, sinkName)) {\n            log.error().attr(\"componentType\", ComponentTypeUtils.toString(componentType)).attr(\"tenant\", tenant)\n\n                    .attr(\"namespace\", namespace).attr(\"componentName\", sinkName).log(\"/ / already exists\");\n            throw new RestException(Response.Status.BAD_REQUEST,\n                    String.format(\"%s %s already exists\", ComponentTypeUtils.toString(componentType), sinkName));\n        }\n\n        FunctionDetails functionDetails;\n        File componentPackageFile = null;\n        try {\n\n            // validate parameters\n            try {\n                if (isNotBlank(sinkPkgUrl)) {\n                    componentPackageFile = getPackageFile(componentType, sinkPkgUrl);\n                    functionDetails = validateUpdateRequestParams(tenant, namespace, sinkName,\n                            sinkConfig, componentPackageFile);\n                } else {\n                    if (uploadedInputStream != null) {\n                        componentPackageFile = WorkerUtils.dumpToTmpFile(uploadedInputStream);\n                    }\n                    functionDetails = validateUpdateRequestParams(tenant, namespace, sinkName,","sourceCodeStart":128,"sourceCodeEnd":164,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/api/SinksImpl.java#L128-L164","documentation":"registerSink checks FunctionMetaDataManager.containsFunction(tenant, namespace, sinkName) and throws a 400 Bad Request RestException when a component of that type already exists at the same coordinates, with message formatted as \"<ComponentType> <sinkName> already exists\" (e.g. \"Sink my-sink already exists\"). Sink names must be unique per tenant/namespace among registered functions/sources/sinks.","triggerScenarios":"Calling the sink creation endpoint (PUT without update semantics / POST create) when a function, source, or sink with the same tenant/namespace/sinkName is already registered in the workers' metadata manager.","commonSituations":"Re-running an idempotency-unsafe deployment script; name collision between a function and a sink sharing a name; CI pipelines retried after a partially successful deploy; teams unaware names are shared across component types.","solutions":["Use the update endpoint (PUT .../sinks/{tenant}/{ns}/{name}) instead of create if you intend to replace the existing sink.","Delete the existing sink first: pulsar-admin sinks delete tenant/ns/name, then create.","Choose a unique sink name for a genuinely new component; remember function/source/sink names share one namespace.","Check existing components with pulsar-admin sinks list tenant/ns before deploying."],"exampleFix":"// before: re-creating an existing sink\ncurl -X POST .../sinks/t/ns/my-sink  # 400 Sink my-sink already exists\n// after: update instead of create\ncurl -X PUT .../sinks/t/ns/my-sink -H \"Content-Type: application/json\" -d @sink-config.json","handlingStrategy":"validation","validationCode":"if (admin.sinks().getSink(tenant, namespace, sinkName) != null) {\n    throw new IllegalStateException(\"Sink \" + sinkName + \" already exists; use update or delete first\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    sinks.registerSink(tenant, ns, name, cfg, null, null, null, authParams);\n} catch (RestException e) {\n    if (e.getResponse().getStatus() == 400 && e.getMessage() != null && e.getMessage().endsWith(\"already exists\")) {\n        // switch to the update endpoint or delete/recreate\n    } else { throw e; }\n}","preventionTips":["Make deployment scripts idempotent: check-then-update instead of unconditional create","Use unique, environment-suffixed component names to avoid cross-team collisions","Remember function/source/sink names share a namespace - check all three when picking a name"],"tags":["rest-api","bad-request","duplicate-resource","pulsar-sinks"],"backgroundTag":"resource-already-exists","analyzedSha":"820761864ed8e2a7d2e52dd9763ad2ae117c1395","analyzedAt":"2026-09-06T00:14:20.138Z","contentChangedAt":"2026-09-06T00:14:20.138Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}