{"record":{"id":"f2cd7abf626bcddf","repo":"apache/pulsar","slug":"resource-group-already-exists-rgname","errorCode":null,"errorMessage":"Resource group already exists:${rgName}","messagePattern":"Resource group already exists:(.+?)","errorType":"exception","errorClass":"PulsarAdminException","httpStatus":null,"severity":"error","filePath":"pulsar-broker/src/main/java/org/apache/pulsar/broker/resourcegroup/ResourceGroupService.java","lineNumber":816,"sourceCode":"        final long periodInSecs = pulsar.getConfiguration().getResourceUsageTransportPublishIntervalInSecs();\n        this.aggregateLocalUsagePeriodInSeconds = this.resourceUsagePublishPeriodInSeconds = periodInSecs;\n        // if any tenant/namespace registrations already exist, maybeStartSchedulers() will start the schedulers now.\n        maybeStartSchedulers();\n    }\n\n    private void checkRGCreateParams(String rgName, org.apache.pulsar.common.policies.data.ResourceGroup rgConfig)\n      throws PulsarAdminException {\n        if (rgConfig == null) {\n            throw new IllegalArgumentException(\"ResourceGroupCreate: Invalid null ResourceGroup config\");\n        }\n\n        if (rgName.isEmpty()) {\n            throw new IllegalArgumentException(\"ResourceGroupCreate: can't create resource group with an empty name\");\n        }\n\n        ResourceGroup rg = getResourceGroupInternal(rgName);\n        if (rg != null) {\n            throw new PulsarAdminException(\"Resource group already exists:\" + rgName);\n        }\n    }\n    @Getter\n    private final PulsarService pulsar;\n\n    protected final ResourceQuotaCalculator quotaCalculator;\n    private ResourceUsageTransportManager resourceUsageTransportManagerMgr;\n\n    // rgConfigListener is used only through its side effects in the ctors, to set up RG/NS loading in config-listeners.\n    private final ResourceGroupConfigListener rgConfigListener;\n\n    // Given a RG-name, get the resource-group\n    private ConcurrentHashMap<String, ResourceGroup> resourceGroupsMap = new ConcurrentHashMap<>();\n\n    // Given a tenant-name, record its associated resource-group\n    private ConcurrentHashMap<String, ResourceGroup> tenantToRGsMap = new ConcurrentHashMap<>();\n\n    // Given a qualified NS-name (i.e., in \"tenant/namespace\" format), record its associated resource-group","sourceCodeStart":798,"sourceCodeEnd":834,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-broker/src/main/java/org/apache/pulsar/broker/resourcegroup/ResourceGroupService.java#L798-L834","documentation":"Thrown as PulsarAdminException when creating a resource group whose name already exists in the broker's resource-group map. Resource group names must be unique, so a duplicate create is rejected instead of overwriting the existing config.","triggerScenarios":"Calling createResourceGroup with a name that was previously created — re-running an initialization script, two services racing to bootstrap the same group, or a retry after a timeout where the first attempt actually succeeded.","commonSituations":"Idempotency issues in deploy scripts; concurrent provisioning jobs; migrating config where the group already exists on the target cluster.","solutions":["Check existence first (getResourceGroupInternal / admin GET) and update instead of create if present","Use an update API (or create-or-update pattern) for idempotent provisioning","Serialize provisioning so concurrent jobs don't race","Catch PulsarAdminException with 'already exists' in the message and treat as success in retry logic"],"exampleFix":"// before\nadmin.resourcegroups().createResourceGroup(\"rg1\", rg); // fails on rerun\n// after\ntry {\n    admin.resourcegroups().createResourceGroup(\"rg1\", rg);\n} catch (PulsarAdminException e) {\n    if (!String.valueOf(e.getMessage()).contains(\"already exists\")) throw e;\n    admin.resourcegroups().updateResourceGroup(\"rg1\", rg);\n}","handlingStrategy":"try-catch","validationCode":"if (admin.resourcegroups().getResourceGroup(rgName) != null) {\n    admin.resourcegroups().updateResourceGroup(rgName, rgConfig);\n} else {\n    admin.resourcegroups().createResourceGroup(rgName, rgConfig);\n}","typeGuard":null,"tryCatchPattern":"try {\n    admin.resourcegroups().createResourceGroup(rgName, rgConfig);\n} catch (PulsarAdminException e) {\n    if (String.valueOf(e.getMessage()).startsWith(\"Resource group already exists\")) {\n        admin.resourcegroups().updateResourceGroup(rgName, rgConfig);\n    } else throw e;\n}","preventionTips":["Make provisioning scripts idempotent (create-or-update)","Serialize provisioning jobs to avoid duplicate-creation races","Treat 'already exists' as non-fatal in retry wrappers"],"tags":["pulsar","admin-api","duplicate","conflict"],"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-14T05:17:10.506Z"}