{"record":{"id":"d90cda57c2ec9f99","repo":"apache/pulsar","slug":"serviceurlprovider-has-already-been-initialized-d90cda","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/ControlledClusterFailover.java","lineNumber":125,"sourceCode":"        confBuilder.setKeepAliveStrategy(new DefaultKeepAliveStrategy() {\n            @Override\n            public boolean keepAlive(InetSocketAddress remoteAddress, Request ahcRequest,\n                                     HttpRequest request, HttpResponse response) {\n                // Close connection upon a server error or per HTTP spec\n                return (response.status().code() / 100 != 5)\n                    && super.keepAlive(remoteAddress, ahcRequest, request, response);\n            }\n        });\n        confBuilder.setNettyTimer(pulsarClient.timer());\n        confBuilder.setEventLoopGroup(pulsarClient.eventLoopGroup());\n        AsyncHttpClientConfig config = confBuilder.build();\n        return new DefaultAsyncHttpClient(config);\n    }\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.pulsarClient = (PulsarClientImpl) client;\n        this.httpClient = buildHttpClient();\n        this.requestBuilder = httpClient.prepareGet(urlProvider)\n                // share Pulsar client DNS resolver and cache\n                .setNameResolver(pulsarClient.getNameResolver())\n                .addHeader(\"Accept\", \"application/json\");\n        headers.forEach(requestBuilder::addHeader);\n\n        // Initialize currentControlledConfiguration from client's current configuration\n        // to avoid unnecessary reconnection on first scheduled check when the configuration hasn't changed\n        ClientConfigurationData conf = pulsarClient.getConfiguration();\n        this.currentControlledConfiguration = new ControlledConfiguration();\n        this.currentControlledConfiguration.setServiceUrl(currentPulsarServiceUrl);\n        this.currentControlledConfiguration.setTlsTrustCertsFilePath(conf.getTlsTrustCertsFilePath());\n        this.currentControlledConfiguration.setAuthPluginClassName(conf.getAuthPluginClassName());\n        this.currentControlledConfiguration.setAuthParamsString(conf.getAuthParams());\n","sourceCodeStart":107,"sourceCodeEnd":143,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-client/src/main/java/org/apache/pulsar/client/impl/ControlledClusterFailover.java#L107-L143","documentation":"ControlledClusterFailover is a ServiceUrlProvider and initialize(PulsarClient) is meant to be called exactly once by the client to wire it up. Calling initialize again while it already holds a pulsarClient reference throws IllegalStateException to prevent leaking HTTP clients and re-binding to a second client.","triggerScenarios":"Calling provider.initialize(client) a second time on the same ControlledClusterFailover instance — e.g. building two PulsarClient instances that share one provider, or re-initializing in tests (as seen in testBuildControlledClusterFailoverInstance / testControlledClusterFailoverSwitch).","commonSituations":"Reusing a single ServiceUrlProvider across multiple PulsarClient instances; unit tests constructing the client twice; hot-reload code that re-runs initialize without recreating the provider.","solutions":["Create a new ControlledClusterFailover instance for each PulsarClient.","Close the existing PulsarClient/provider and build a fresh pair instead of re-initializing.","In tests, construct the provider inside the test setup for each case rather than sharing a field."],"exampleFix":"// before\nprovider.initialize(client1);\nprovider.initialize(client2); // throws\n// after\nControlledClusterFailover p2 = ControlledClusterFailover.builder().urlProvider(...).defaultServiceUrl(...).build();\np2.initialize(client2);","handlingStrategy":"validation","validationCode":"if (provider instanceof ControlledClusterFailover ccf) {\n  // build a fresh instance per client instead of re-initializing\n}","typeGuard":null,"tryCatchPattern":"try {\n  provider.initialize(client);\n} catch (IllegalStateException e) {\n  provider = ControlledClusterFailover.builder()...build(); // recreate\n  provider.initialize(client);\n}","preventionTips":["Create a new ServiceUrlProvider instance for every PulsarClient.","Never call initialize() twice on the same provider; close and rebuild instead.","In tests, instantiate the provider in setup per test case."],"tags":["pulsar","serviceurlprovider","configuration","lifecycle"],"backgroundTag":"already-initialized","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"}