apache/pulsar · error · java.lang.IllegalArgumentException
${fieldName} must use the broker binary protocol (pulsar://
Error message
${fieldName} must use the broker binary protocol (pulsar:// or pulsar+ssl://); got '${url}'. This looks like the admin/web service URL — pass the broker service URL instead (typically port 6650, or 6651 for TLS). What it means
The v5 builder validates that the service URL uses the broker binary protocol (pulsar:// or pulsar+ssl://). An http:// or https:// URL is almost always the admin/web service URL (port 8080/6651-style web endpoint), which would otherwise cause confusing downstream connection failures; the builder rejects it at configure time and tells you to use the broker URL (typically port 6650, or 6651 for TLS). Any other scheme gets the same message without the 'admin/web' hint.
Source
Thrown at pulsar-client-v5/src/main/java/org/apache/pulsar/client/impl/v5/PulsarClientBuilderV5.java:591
return conf;
}
/**
* Reject anything that isn't the broker binary protocol. The most common
* mistake is passing the admin/web service URL ({@code http://...}) where a
* broker URL is expected — call that out specifically. The v4 client used to
* silently fail far downstream with cryptic connection errors; here we fail
* fast at configure time with a message the user can act on.
*/
private static void validatePulsarServiceUrl(String url, String fieldName) {
if (url == null || url.isBlank()) {
throw new IllegalArgumentException(fieldName + " must not be null or blank");
}
if (url.startsWith("pulsar://") || url.startsWith("pulsar+ssl://")) {
return;
}
if (url.startsWith("http://") || url.startsWith("https://")) {
throw new IllegalArgumentException(fieldName + " must use the broker binary protocol "
+ "(pulsar:// or pulsar+ssl://); got '" + url + "'. This looks like the admin/web "
+ "service URL — pass the broker service URL instead (typically port 6650, or "
+ "6651 for TLS).");
}
throw new IllegalArgumentException(fieldName + " must use the broker binary protocol "
+ "(pulsar:// or pulsar+ssl://); got '" + url + "'.");
}
}
View on GitHub (pinned to 820761864e)
Solutions
- Replace the URL with the broker binary URL: pulsar://host:6650 (or pulsar+ssl://host:6651 for TLS).
- Keep the http(s) URL only for the PulsarAdmin client, not the messaging client.
- Check broker.conf: webServiceUrl (http) is for admin, brokerServiceUrl (pulsar://) is what the client needs.
- If you need to connect through a proxy, set proxyServiceUrl within ConnectionPolicy with a pulsar:// URL and the matching proxyProtocol, not an http URL.
Example fix
// before
PulsarClient c = PulsarClient.builder()
.serviceUrl("http://localhost:8080") // admin URL -> IllegalArgumentException
.build();
// after
PulsarClient c = PulsarClient.builder()
.serviceUrl("pulsar://localhost:6650")
.build(); Defensive patterns
Strategy: validation
Validate before calling
String url = envOrConfig("serviceUrl");
if (url != null && (url.startsWith("http://") || url.startsWith("https://"))) {
throw new IllegalStateException("serviceUrl must be pulsar://... — " + url + " looks like the admin URL");
} Type guard
static boolean isBrokerUrl(String u) {
return u != null && (u.startsWith("pulsar://") || u.startsWith("pulsar+ssl://"));
} Try / catch
try {
builder.serviceUrl(url);
} catch (IllegalArgumentException e) {
if (e.getMessage().contains("broker binary protocol")) {
throw new IllegalStateException("Point the messaging client at pulsar://host:6650, not the admin URL", e);
}
throw e;
} Prevention
- Keep admin URL and broker URL as separate named config keys (adminUrl vs serviceUrl).
- Broker port is typically 6650 (6651 for TLS); admin/web is 8080 — check broker.conf's brokerServiceUrl.
- Add a scheme check helper in shared client-factory code.
- For proxies, use ConnectionPolicy.proxyServiceUrl with a pulsar:// URL plus proxyProtocol, not an http URL.
When it happens
Trigger: Calling builder.serviceUrl("http://broker:8080") or serviceUrl("https://...") — or connectionPolicy with a proxyServiceUrl of that shape — then build()/further configuration triggers the validation immediately.
Common situations: Copy-pasting the admin URL from broker.conf (webServiceUrl) or from a Pulsar Admin client example; using the standalone-service URL from docker-compose; confusing the REST proxy endpoint with the binary endpoint; defaulting to port 8080 from other middleware.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- ${fieldName} must not be null or blank
- there are redundant configure for listener `${listenerName}`
- must not specify `${hostPort}` to different listener.
- the value ${strUri} in the `advertisedListeners` configure i
- When Guarantees == ATMOST_ONCE, autoAck must be equal to tru
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/b380d0a76ad7d359.
Report an issue: GitHub.