apache/pulsar · error · java.lang.IllegalArgumentException
${fieldName} must not be null or blank
Error message
${fieldName} must not be null or blank What it means
validatePulsarServiceUrl rejects a null or blank URL at configure time. The v4 client used to fail far downstream with cryptic connection errors when given an empty service URL; the v5 builder fails fast in serviceUrl(String) or connectionPolicy's proxyServiceUrl handling with a message naming the offending field.
Source
Thrown at pulsar-client-v5/src/main/java/org/apache/pulsar/client/impl/v5/PulsarClientBuilderV5.java:585
conf.setDescription(description);
return this;
}
/** @return the underlying v4 configuration data; for tests in this package only. */
ClientConfigurationData getConfForTesting() {
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
- Set the service URL explicitly: builder.serviceUrl("pulsar://localhost:6650").
- Check where the URL comes from (env var, config file) and fix the missing/blank value before building.
- Provide a sensible default for local development and fail with your own message in higher environments.
- If proxyServiceUrl is the culprit, either set a valid pulsar:// URL or leave it null in the ConnectionPolicy (null means not configured).
Example fix
// before
String url = System.getenv("PULSAR_URL");
builder.serviceUrl(url); // IllegalArgumentException if unset
// after
String url = System.getenv("PULSAR_URL");
Objects.requireNonNull(url, "PULSAR_URL must be set");
builder.serviceUrl(url); Defensive patterns
Strategy: validation
Validate before calling
String url = envOrConfig("serviceUrl");
if (url == null || url.isBlank()) {
throw new IllegalStateException("serviceUrl is not configured (check env/config)");
}
builder.serviceUrl(url); Type guard
static boolean isNonBlank(String s) { return s != null && !s.isBlank(); } Try / catch
try {
builder.serviceUrl(url);
} catch (IllegalArgumentException e) {
if (e.getMessage().endsWith("must not be null or blank")) {
throw new IllegalStateException("Missing serviceUrl configuration", e);
}
throw e;
} Prevention
- Fail your own startup fast when the URL env/config key is missing, with a message naming the key.
- Give defaults for local dev (pulsar://localhost:6650) but never for production.
- Validate all externalized config in one place before constructing clients.
When it happens
Trigger: Calling builder.serviceUrl(null), serviceUrl(""), serviceUrl(" "), or connectionPolicy with a ConnectionPolicy whose proxyServiceUrl is set to null/blank through the validating path; typically from an environment variable or config key that is unset.
Common situations: Missing SERVICE_URL / PULSAR_SERVICE_URL environment variable; properties file key typo so the default null survives; an empty YAML/config value; calling serviceUrl with the result of a lookup that returned Optional.empty-mapped-to-null.
Related errors
- ${fieldName} must use the broker binary protocol (pulsar://
- 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/991c2543066fbe20.
Report an issue: GitHub.