{"record":{"id":"79c502a61c3aa938","repo":"apache/pulsar","slug":"pulsarserviceurlarray-contains-duplicated-value","errorCode":null,"errorMessage":"pulsarServiceUrlArray contains duplicated value ","messagePattern":"pulsarServiceUrlArray contains duplicated value ","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"pulsar-client/src/main/java/org/apache/pulsar/client/impl/SameAuthParamsLookupAutoClusterFailover.java","lineNumber":371,"sourceCode":"\n        public Builder pulsarServiceUrlArray(String[] pulsarServiceUrlArray) {\n            if (pulsarServiceUrlArray == null || pulsarServiceUrlArray.length == 0) {\n                throw new IllegalArgumentException(\"pulsarServiceUrlArray can not be empty\");\n            }\n            sameAuthParamsLookupAutoClusterFailover.pulsarServiceUrlArray = pulsarServiceUrlArray;\n            int pulsarServiceLen = pulsarServiceUrlArray.length;\n            HashSet<String> uniqueChecker = new HashSet<>();\n            for (int i = 0; i < pulsarServiceLen; i++) {\n                String pulsarService = pulsarServiceUrlArray[i];\n                if (StringUtils.isBlank(pulsarService)) {\n                    throw new IllegalArgumentException(\"pulsarServiceUrlArray contains a blank value at index \" + i);\n                }\n                if (pulsarService.startsWith(\"http\") || pulsarService.startsWith(\"HTTP\")) {\n                    throw new IllegalArgumentException(\"SameAuthParamsLookupAutoClusterFailover does not support HTTP\"\n                            + \" protocol pulsar service url so far.\");\n                }\n                if (!uniqueChecker.add(pulsarService)) {\n                    throw new IllegalArgumentException(\"pulsarServiceUrlArray contains duplicated value \"\n                            + pulsarServiceUrlArray[i]);\n                }\n            }\n            return this;\n        }\n\n        public SameAuthParamsLookupAutoClusterFailover build() {\n            String[] pulsarServiceUrlArray = sameAuthParamsLookupAutoClusterFailover.pulsarServiceUrlArray;\n            if (pulsarServiceUrlArray == null) {\n                throw new IllegalArgumentException(\"pulsarServiceUrlArray can not be empty\");\n            }\n            int pulsarServiceLen = pulsarServiceUrlArray.length;\n            sameAuthParamsLookupAutoClusterFailover.pulsarServiceStateArray = new PulsarServiceState[pulsarServiceLen];\n            sameAuthParamsLookupAutoClusterFailover.checkCounterArray = new MutableInt[pulsarServiceLen];\n            for (int i = 0; i < pulsarServiceLen; i++) {\n                sameAuthParamsLookupAutoClusterFailover.pulsarServiceStateArray[i] = PulsarServiceState.Healthy;\n                sameAuthParamsLookupAutoClusterFailover.checkCounterArray[i] = new MutableInt(0);\n            }","sourceCodeStart":353,"sourceCodeEnd":389,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-client/src/main/java/org/apache/pulsar/client/impl/SameAuthParamsLookupAutoClusterFailover.java#L353-L389","documentation":"Builder.pulsarServiceUrlArray enforces that all provided cluster URLs are distinct; it uses a HashSet and throws IllegalArgumentException when a duplicate entry is added, since failing over between two identical clusters is pointless and would mask misconfiguration.","triggerScenarios":"Calling pulsarServiceUrlArray with the same URL appearing two or more times (exact string match, so also different-case or with a trailing slash vs without), e.g. 'pulsar://a:6650,pulsar://a:6650' from a config merge.","commonSituations":"Config layering (defaults + overrides) concatenating cluster lists without deduplication; copy-paste duplication when adding a cluster; environment variables appended repeatedly.","solutions":["Deduplicate the array (e.g. new LinkedHashSet<>(Arrays.asList(urls))) before passing it to the builder.","Fix the source configuration so each cluster is listed exactly once.","If deduplication changes behavior you relied on, redesign the cluster list — duplicates are never valid here."],"exampleFix":"// before\nbuilder.pulsarServiceUrlArray(cfg.getClusterList().toArray(new String[0])); // may contain dupes\n\n// after\nString[] urls = cfg.getClusterList().stream().distinct().toArray(String[]::new);\nbuilder.pulsarServiceUrlArray(urls);","handlingStrategy":"validation","validationCode":"String[] urls = cfg.getClusterList().stream().distinct().toArray(String[]::new);\nif (urls.length != cfg.getClusterList().size()) {\n    log.warn(\"Duplicate cluster URLs removed from configuration\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    builder.pulsarServiceUrlArray(urls);\n} catch (IllegalArgumentException e) {\n    log.error(\"Duplicate cluster URL in configuration: {}\", e.getMessage());\n    throw new ConfigurationException(\"Each cluster URL must be unique\", e);\n}","preventionTips":["Deduplicate cluster lists (LinkedHashSet) before passing them to the builder.","Avoid concatenating default and override cluster lists without a merge strategy.","Normalize URL strings (trim, consistent case) before deduplication checks."],"tags":["pulsar-client","configuration","validation","illegal-argument"],"backgroundTag":"invalid-config-value","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"}