apache/pulsar · error · IllegalArgumentException
No usable leader URL (useTls=<tls>, url=<url>, urlTls=<urlTl
Error message
No usable leader URL (useTls=<tls>, url=<url>, urlTls=<urlTls>)
What it means
WatchTcAssignmentsDiscovery.selectLeaderUri picks the leader broker URI for transaction coordinator assignments watching: the TLS variant (urlTls) when the client is configured with useTls, otherwise the plain url. If the chosen URL is null or blank, an IllegalArgumentException reports all three inputs. The broker discovery data did not provide a usable service URL for the current TLS setting.
Source
Thrown at pulsar-client/src/main/java/org/apache/pulsar/client/impl/transaction/WatchTcAssignmentsDiscovery.java:235
private void scheduleReconnect() {
if (closed) {
return;
}
long delayMs = reconnectBackoff.next().toMillis();
pulsarClient.timer().newTimeout(timeout -> openWatch(), delayMs, TimeUnit.MILLISECONDS);
}
/**
* Pick the leader URL matching the client's TLS setting and parse it. Throws if no usable URL is
* present (e.g. a non-TLS client and a TLS-only leader) — the caller skips that partition rather
* than tearing down the watch.
*/
private URI selectLeaderUri(String url, String urlTls) {
boolean tls = pulsarClient.getConfiguration().isUseTls();
String chosen = tls && urlTls != null && !urlTls.isBlank() ? urlTls : url;
if (chosen == null || chosen.isBlank()) {
throw new IllegalArgumentException("No usable leader URL (useTls=" + tls
+ ", url=" + url + ", urlTls=" + urlTls + ")");
}
return URI.create(chosen);
}
@Override
public TransactionMetaStoreHandler handlerForCoordinator(long tcId) {
return handlers.get(tcId);
}
@Override
public TransactionMetaStoreHandler nextHandler() {
int n = parallelism;
if (n <= 0) {
return null;
}
// Round-robin over coordinator ids 0..parallelism-1, skipping any mid-election gap.
for (int attempt = 0; attempt < n; attempt++) {View on GitHub (pinned to 820761864e)
Solutions
- Configure the broker's TLS web service URL (webServiceUrlTls=https://...) so urlTls is populated when useTls=true.
- Set the client's serviceUrl to match the advertised scheme (https://... when useTls) or disable useTls.
- Verify the discovery response actually contains a non-empty serviceUrl; check broker registration config.
- If you control the lookup, ensure advertisedListeners/serviceUrl fields are correctly set on the broker.
Example fix
// before (broker.conf) webServiceUrl=http://host:8080 // after (when clients use TLS) webServiceUrlTls=https://host:8443
Defensive patterns
Strategy: validation
Validate before calling
boolean usable(String u) { return u != null && !u.isBlank(); }
String url = discovery.getUrl(), urlTls = discovery.getUrlTls();
boolean ok = clientConf.isUseTls() ? usable(urlTls) || usable(url) : usable(url);
if (!ok) throw new IllegalStateException("Discovery gave no usable service URL"); Try / catch
try {
watchTcAssignments();
} catch (IllegalArgumentException e) {
if (e.getMessage().startsWith("No usable leader URL")) {
log.error("Broker missing serviceUrl/webServiceUrlTls for useTls=" + useTls, e);
}
} Prevention
- Configure webServiceUrlTls on brokers when clients use TLS
- Keep client serviceUrl scheme consistent with useTls
- Inspect discovery payloads in tests for null/blank URLs
- Pin broker/client versions when listener advertisement schemas change
When it happens
Trigger: Receiving a discovery event where url (and urlTls, when useTls=true) is null/empty, then attempting to derive the leader URI for the watch.
Common situations: Broker advertising only a plain HTTP service URL while the client requires TLS (useTls=true, no tls service URL configured); broker misconfiguration missing webServiceUrl/webServiceUrlTls; discovery data truncated or from an older broker version.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- The replication cluster does not provide TLS encrypted servi
- No ${scheme} URL configured for broker ${brokerId}
- Invalid txnId key:
- Transaction pending ack replay error with illegal state :
- Transaction recover tracker`
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/887c9eb497f1e314.
Report an issue: GitHub.