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

  1. Replace the URL with the broker binary URL: pulsar://host:6650 (or pulsar+ssl://host:6651 for TLS).
  2. Keep the http(s) URL only for the PulsarAdmin client, not the messaging client.
  3. Check broker.conf: webServiceUrl (http) is for admin, brokerServiceUrl (pulsar://) is what the client needs.
  4. 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

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

Related errors


AI-assisted analysis of apache/pulsar@820761864e (2026-09-06). Data as JSON: /api/errors/b380d0a76ad7d359. Report an issue: GitHub.