apache/pulsar · error · IllegalArgumentException

the `advertisedListeners` configuration does not contain an

Error message

the `advertisedListeners` configuration does not contain an entry for the internal listener `${internalListenerName}`, and the legacy port properties are not configured so an internal listener cannot be synthesized

What it means

IllegalArgumentException thrown by MultipleListenerValidator.validateAndUpdateAdvertisedListeners when advertisedListeners is non-empty but contains no entry for the configured internal listener, and the legacy port properties (port/portTls/portHttp/portHttps) are not set, so an internal listener cannot be synthesized by merging legacy ports. Every broker must know its internal listener for broker-to-broker and client redirect URLs.

Source

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

            String fallback = result.isEmpty()
                    ? ServiceConfiguration.DEFAULT_INTERNAL_LISTENER_NAME
                    : result.keySet().iterator().next();
            config.setInternalListenerName(fallback);
        }
        String internalListenerName = config.getInternalListenerName();

        // Merge the legacy-port-derived internal listener URLs into any explicit configuration.
        // Explicit URLs in `advertisedListeners` take precedence; the legacy-port URLs fill in the
        // unspecified slots so that broker-to-broker communication keeps working without forcing the
        // user to redeclare every URL when they only want to override one.
        AdvertisedListener fromLegacyPorts = buildInternalListenerFromLegacyPorts(config);
        if (fromLegacyPorts != null) {
            AdvertisedListener explicit = result.get(internalListenerName);
            result.put(internalListenerName, mergeListeners(explicit, fromLegacyPorts));
        }

        if (!result.isEmpty() && !result.containsKey(internalListenerName)) {
            throw new IllegalArgumentException("the `advertisedListeners` configuration does not contain "
                    + "an entry for the internal listener `" + internalListenerName + "`, and the legacy "
                    + "port properties are not configured so an internal listener cannot be synthesized");
        }

        return result;
    }

    /**
     * Merges two {@link AdvertisedListener} entries. URLs from {@code override} take precedence; URLs
     * from {@code fallback} only fill in the slots that {@code override} leaves null. Either argument
     * may be null.
     */
    private static AdvertisedListener mergeListeners(AdvertisedListener override, AdvertisedListener fallback) {
        if (override == null) {
            return fallback;
        }
        if (fallback == null) {
            return override;

View on GitHub (pinned to 820761864e)

Solutions

  1. Add an entry for the internal listener to advertisedListeners, e.g. internal:pulsar://<advertised-host>:6650
  2. Or set internalListenerName to one of the names present in advertisedListeners
  3. Or keep the legacy port (and portTls) properties so an internal listener can be synthesized and merged
  4. Ensure internalListenerName matches an advertisedListeners key exactly

Example fix

// before
advertisedListeners=external:pulsar+ssl://broker.example.com:6651
internalListenerName=internal
// after
advertisedListeners=external:pulsar+ssl://broker.example.com:6651,internal:pulsar://10.0.0.5:6650
internalListenerName=internal
Defensive patterns

Strategy: validation

Validate before calling

Map<String,String> listeners = parseAdvertisedListeners(conf.getAdvertisedListeners());
String internal = conf.getInternalListenerName();
boolean legacyPortsSet = conf.getPort() > 0 || conf.getPortTls() > 0;
if (!listeners.isEmpty() && !listeners.containsKey(internal) && !legacyPortsSet) {
    throw new IllegalArgumentException("advertisedListeners must contain internal listener '" + internal + "' or legacy ports must be set");
}

Prevention

When it happens

Trigger: Setting advertisedListeners to names other than the internalListenerName config value (e.g. listeners named 'external' only) while removing the legacy port/portTls properties; renaming a listener without updating internalListenerName; upgrading from a legacy single-listener config and dropping port properties while giving advertisedListeners different names.

Common situations: Helm/k8s deployments where advertisedListeners was templated for external access but internalListenerName kept its default; operators migrating off legacy ports to multi-listener config; typo where the internal listener key differs by case or suffix.

Related errors


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