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
- Add an entry for the internal listener to advertisedListeners, e.g. internal:pulsar://<advertised-host>:6650
- Or set internalListenerName to one of the names present in advertisedListeners
- Or keep the legacy port (and portTls) properties so an internal listener can be synthesized and merged
- 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
- Always include the internal listener in advertisedListeners
- Keep internalListenerName in sync when renaming listeners
- Retain legacy port properties during migrations as a safety net
- Assert the invariant in deployment charts before apply
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
- bindAddresses: malformed: ${address}
- the configure entry `advertisedListeners` is invalid. becaus
- webServicePort/webServicePortTls or http/https bindAddresses
- The retention size must > the backlog quota limit size, but
- The retention time must > the backlog quota limit time, but
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/1601809196625105.
Report an issue: GitHub.