{"record":{"id":"a546f889c537997e","repo":"apache/pulsar","slug":"serviceurlprovider-has-already-been-initialized-a546f8","errorCode":null,"errorMessage":"ServiceUrlProvider has already been initialized","messagePattern":"ServiceUrlProvider has already been initialized","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"pulsar-client/src/main/java/org/apache/pulsar/client/impl/SameAuthParamsLookupAutoClusterFailover.java","lineNumber":78,"sourceCode":"    @Getter\n    private long checkHealthyIntervalMs = 1000;\n    @Getter\n    private boolean markTopicNotFoundAsAvailable = true;\n    @Getter\n    private String testTopic = \"public/default/tp_test\";\n\n    private String[] pulsarServiceUrlArray;\n    private PulsarServiceState[] pulsarServiceStateArray;\n    private MutableInt[] checkCounterArray;\n    @Getter\n    private volatile int currentPulsarServiceIndex;\n\n    private SameAuthParamsLookupAutoClusterFailover() {}\n\n    @Override\n    public synchronized void initialize(PulsarClient client) {\n        if (this.pulsarClient != null) {\n            throw new IllegalStateException(\"ServiceUrlProvider has already been initialized\");\n        }\n        this.currentPulsarServiceIndex = 0;\n        this.pulsarClient = (PulsarClientImpl) client;\n        this.executor = Executors.newSingleThreadScheduledExecutor(\n                new ExecutorProvider.ExtendedThreadFactory(\"broker-service-url-check\"));\n        // Use fixed-delay (not fixed-rate) scheduling: a probe can block up to its timeout, and with a\n        // plain single-threaded scheduled executor fixed-rate runs would otherwise pile up back-to-back\n        // and monopolize the thread. Fixed-delay leaves a gap after each check completes.\n        scheduledCheckTask = executor.scheduleWithFixedDelay(() -> {\n            try {\n                if (closed) {\n                    return;\n                }\n                checkPulsarServices();\n                int firstHealthyPulsarService = firstHealthyPulsarService();\n                if (firstHealthyPulsarService == currentPulsarServiceIndex) {\n                    return;\n                }","sourceCodeStart":60,"sourceCodeEnd":96,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-client/src/main/java/org/apache/pulsar/client/impl/SameAuthParamsLookupAutoClusterFailover.java#L60-L96","documentation":"SameAuthParamsLookupAutoClusterFailover is a ServiceUrlProvider that can be attached to exactly one PulsarClient. initialize() throws IllegalStateException if initialize() has already been called successfully, because re-initializing would clobber the existing client reference, executor, and scheduled probe task.","triggerScenarios":"Calling initialize(client) a second time on the same SameAuthParamsLookupAutoClusterFailover instance, e.g. reusing one builder-produced provider across multiple PulsarClient instances or retrying client construction with the same provider object.","commonSituations":"Application restart logic that re-creates a PulsarClient but reuses the shared ServiceUrlProvider singleton; configuration reload code that calls initialize again on the same instance instead of building a new one.","solutions":["Create a fresh SameAuthParamsLookupAutoClusterFailover instance (via its Builder) for every PulsarClient you construct.","If you must reuse configuration, keep the Builder/config around and build a new provider instead of re-calling initialize on the old one.","Guard your initialization code so initialize() is invoked at most once per provider instance (check your own lifecycle flag)."],"exampleFix":"// before\nAutoClusterFailoverConfig config = ...;\nSameAuthParamsLookupAutoClusterFailover provider = SameAuthParamsLookupAutoClusterFailover.builder()...build();\nPulsarClient c1 = PulsarClient.builder().serviceUrlProvider(provider).create();\nPulsarClient c2 = PulsarClient.builder().serviceUrlProvider(provider).create(); // throws\n\n// after\nPulsarClient c2 = PulsarClient.builder()\n    .serviceUrlProvider(SameAuthParamsLookupAutoClusterFailover.builder()...build())\n    .create();","handlingStrategy":"validation","validationCode":"if (provider instanceof SameAuthParamsLookupAutoClusterFailover\n        && isAlreadyInitialized(provider)) {\n    provider = SameAuthParamsLookupAutoClusterFailover.builder()...build();\n}","typeGuard":null,"tryCatchPattern":"try {\n    provider.initialize(client);\n} catch (IllegalStateException e) {\n    // provider already attached to a client: build a new one and retry once\n    provider = buildNewProvider(config);\n    provider.initialize(client);\n}","preventionTips":["Treat each ServiceUrlProvider instance as single-use per PulsarClient.","Store the Builder/config, not the built provider, in shared DI state.","Create the provider and client together in one factory method."],"tags":["pulsar-client","lifecycle","initialization","illegal-state"],"backgroundTag":"already-initialized","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"}