apache/pulsar · error · IllegalStateException
ServiceUrlProvider has already been initialized
Error message
ServiceUrlProvider has already been initialized
What it means
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.
Source
Thrown at pulsar-client/src/main/java/org/apache/pulsar/client/impl/SameAuthParamsLookupAutoClusterFailover.java:78
@Getter
private long checkHealthyIntervalMs = 1000;
@Getter
private boolean markTopicNotFoundAsAvailable = true;
@Getter
private String testTopic = "public/default/tp_test";
private String[] pulsarServiceUrlArray;
private PulsarServiceState[] pulsarServiceStateArray;
private MutableInt[] checkCounterArray;
@Getter
private volatile int currentPulsarServiceIndex;
private SameAuthParamsLookupAutoClusterFailover() {}
@Override
public synchronized void initialize(PulsarClient client) {
if (this.pulsarClient != null) {
throw new IllegalStateException("ServiceUrlProvider has already been initialized");
}
this.currentPulsarServiceIndex = 0;
this.pulsarClient = (PulsarClientImpl) client;
this.executor = Executors.newSingleThreadScheduledExecutor(
new ExecutorProvider.ExtendedThreadFactory("broker-service-url-check"));
// Use fixed-delay (not fixed-rate) scheduling: a probe can block up to its timeout, and with a
// plain single-threaded scheduled executor fixed-rate runs would otherwise pile up back-to-back
// and monopolize the thread. Fixed-delay leaves a gap after each check completes.
scheduledCheckTask = executor.scheduleWithFixedDelay(() -> {
try {
if (closed) {
return;
}
checkPulsarServices();
int firstHealthyPulsarService = firstHealthyPulsarService();
if (firstHealthyPulsarService == currentPulsarServiceIndex) {
return;
}View on GitHub (pinned to 820761864e)
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).
Example fix
// before
AutoClusterFailoverConfig config = ...;
SameAuthParamsLookupAutoClusterFailover provider = SameAuthParamsLookupAutoClusterFailover.builder()...build();
PulsarClient c1 = PulsarClient.builder().serviceUrlProvider(provider).create();
PulsarClient c2 = PulsarClient.builder().serviceUrlProvider(provider).create(); // throws
// after
PulsarClient c2 = PulsarClient.builder()
.serviceUrlProvider(SameAuthParamsLookupAutoClusterFailover.builder()...build())
.create(); Defensive patterns
Strategy: validation
Validate before calling
if (provider instanceof SameAuthParamsLookupAutoClusterFailover
&& isAlreadyInitialized(provider)) {
provider = SameAuthParamsLookupAutoClusterFailover.builder()...build();
} Try / catch
try {
provider.initialize(client);
} catch (IllegalStateException e) {
// provider already attached to a client: build a new one and retry once
provider = buildNewProvider(config);
provider.initialize(client);
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Pulsar client has been closed, can not build LookupService w
- Authentication already closed.
- Failed to initialize OAuth2 IdP TLS factory: ${cause.getMess
- PulsarHttpClientFactory for ${clientInstanceId} is closed
- SASL authentication HTTP client is not started
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/a546f889c537997e.
Report an issue: GitHub.