apache/pulsar · error · IllegalArgumentException

host must not be null

Error message

host must not be null

What it means

IllegalArgumentException thrown by MultipleListenerValidator.formatHostPort(URI) when the URI's host component is null. A URI like pulsar:///path or one with an unparseable authority yields getHost()==null; since the helper must render host:port for advertised-listener validation, it fails fast instead of producing a malformed host string.

Source

Thrown at pulsar-broker-common/src/main/java/org/apache/pulsar/broker/validator/MultipleListenerValidator.java:52

/**
 * Validates multiple listener address configurations.
 */
public final class MultipleListenerValidator {

    /** Allowed listener-name characters: ASCII letters, digits, underscore, hyphen. */
    private static final Pattern LISTENER_NAME_PATTERN = Pattern.compile("[A-Za-z0-9_-]+");

    /**
     * Format the host:port part of a URI for use as a uniqueness key and in error messages, wrapping
     * IPv6 literals in brackets so that the colon separator is unambiguous. {@link URI#getHost()} may
     * or may not include the brackets depending on the JDK, so they are stripped before the
     * {@link NetUtil#isValidIpV6Address} check.
     */
    static String formatHostPort(URI uri) {
        String host = uri.getHost();
        if (host == null) {
            throw new IllegalArgumentException("host must not be null");
        }
        String unbracketed = host.startsWith("[") && host.endsWith("]")
                ? host.substring(1, host.length() - 1) : host;
        if (NetUtil.isValidIpV6Address(unbracketed)) {
            return "[" + unbracketed + "]:" + uri.getPort();
        }
        return host + ":" + uri.getPort();
    }

    /**
     * Validate a listener name. Listener names must be non-blank and contain only ASCII letters,
     * digits, underscore, and hyphen so they are safe to embed in URLs without encoding.
     *
     * @throws IllegalArgumentException if the name is null, blank, or contains disallowed characters.
     */
    public static void validateListenerName(String name) {
        if (StringUtils.isBlank(name)) {
            throw new IllegalArgumentException("listener name must not be blank");

View on GitHub (pinned to 820761864e)

Solutions

  1. Always include an explicit host in listener URLs; bracket IPv6 addresses: pulsar://[fe80::1]:6650
  2. Check the URL with new URI(s) and assert getHost() != null before passing it in
  3. Remove illegal characters from the hostname
  4. If constructing URIs programmatically, use URI(scheme, host, port, ...) so the host is encoded correctly

Example fix

// before
String url = "pulsar://fe80::1:6650"; // getHost() == null
// after
String url = "pulsar://[fe80::1]:6650"; // getHost() == "fe80::1"
Defensive patterns

Strategy: validation

Validate before calling

static boolean hasHost(String listenerUrl) {
    try {
        URI uri = URI.create(listenerUrl);
        return uri.getHost() != null && !uri.getHost().isEmpty();
    } catch (IllegalArgumentException e) {
        return false;
    }
}

Type guard

static boolean isParseableListenerUri(URI uri) {
    return uri != null && uri.getHost() != null;
}

Prevention

When it happens

Trigger: Passing a URI built from a listener URL with no host (e.g. pulsar://:6650) or an authority the JDK URI parser cannot decompose (unbracketed IPv6 like pulsar://fe80::1:6650, illegal characters in the host) — getHost() returns null in both cases.

Common situations: Writing IPv6 advertised listeners without square brackets; omitting the host and keeping only the port; typos or special characters in hostnames that make URI parsing fail silently to null host.

Related errors


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