apache/pulsar · error · IllegalStateException
Pulsar client has been closed, can not build LookupService…
Error message
Pulsar client has been closed, can not build LookupService when calling get lookup with an url
What it means
getLookup(String serviceUrl) lazily builds a LookupService for a URL. If the client has already been closed, building a new lookup service is impossible, so it throws IllegalStateException asking the caller not to build a lookup after close. This surfaces when code holds a client reference past close() and still queries URL-to-lookup mappings.
Solutions
- Ensure getLookup is only called while the client is open — check client.isClosed() first or restructure shutdown ordering.
- Create a new PulsarClient instance if lookups are needed after the previous one was closed.
- Guard shared client references with lifecycle management so no component uses them post-close.
Example fix
// before
client.close();
LookupService ls = client.getLookup(url); // IllegalStateException
// after
if (!client.isClosed()) {
LookupService ls = client.getLookup(url);
} Defensive patterns
Strategy: validation
Validate before calling
if (client.isClosed()) {
throw new IllegalStateException("Refusing getLookup(): client already closed");
}
LookupService ls = client.getLookup(url); Try / catch
try {
LookupService ls = client.getLookup(url);
} catch (IllegalStateException e) {
if (e.getMessage().contains("has been closed")) {
client = recreateClient(); // rebuild a fresh client for further lookups
ls = client.getLookup(url);
} else throw e;
} Prevention
- Check isClosed() before any use of a shared client reference.
- Order shutdown so components using getLookup() stop before client.close() runs.
- Wrap client access in a lifecycle manager that recreates the client on demand.
When it happens
Trigger: Calling client.getLookup(url) (public method) after client.close() has completed, or from another thread while the client is being closed.
Common situations: Shutdown hooks or cleanup code that touches the client after close; long-lived caches holding a closed PulsarClient; race between a close() in one thread and getLookup() in another.
Related errors
- the PulsarTlsFactory passed to tlsFactory(...) has already…
- Cannot decode a message without schema
- Cannot set resourceTypes when shareConfigured() has already…
- Cannot use shareConfigured() when resourceTypes has already…
- ${cause}
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/ea439b84b1fcb855.
Report an issue: GitHub.
Appendix: source
Thrown at pulsar-client/src/main/java/org/apache/pulsar/client/impl/PulsarClientImpl.java:1783
/**
* Only for test.
*/
@VisibleForTesting
public CompletableFuture<ClientCnx> getConnection(final String topic) {
return getConnection(topic, cnxPool.genRandomKeyToSelectCon()).thenApply(Pair::getLeft);
}
public CompletableFuture<ClientCnx> getConnection(final String topic, final String url) {
TopicName topicName = TopicName.get(topic);
return getLookup(url).getBroker(topicName)
.thenCompose(lookupResult -> getConnection(lookupResult.getLogicalAddress(),
lookupResult.getPhysicalAddress(), cnxPool.genRandomKeyToSelectCon()));
}
public LookupService getLookup(String serviceUrl) {
return urlLookupMap.computeIfAbsent(serviceUrl, url -> {
if (isClosed()) {
throw new IllegalStateException("Pulsar client has been closed, can not build LookupService when"
+ " calling get lookup with an url");
}
try {
return createLookup(serviceUrl);
} catch (PulsarClientException e) {
log.warn().attr("service", url).exceptionMessage(e).log("Failed to update url to lookup service");
throw new IllegalStateException("Failed to update url " + url);
}
});
}
public CompletableFuture<ClientCnx> getConnectionToServiceUrl() {
if (!lookup.isBinaryProtoLookupService()) {
return FutureUtil.failedFuture(new PulsarClientException.InvalidServiceURL(
"Can't get client connection to HTTP service URL", null));
}
InetSocketAddress address = lookup.resolveHost();
return getConnection(address, address, cnxPool.genRandomKeyToSelectCon());View on GitHub (pinned to 820761864e)