apache/pulsar · error · IllegalArgumentException
bindAddresses: malformed: ${address}
Error message
bindAddresses: malformed: ${address} What it means
IllegalArgumentException thrown by BindAddressValidator.validateBindAddresses when an entry in the broker's bindAddresses configuration does not match the required pattern listenerName:scheme://host:port (e.g. mylistener:pulsar://127.0.0.1:6650). The validator splits bindAddresses on commas and requires each non-empty segment to fully match BIND_ADDRESSES_PATTERN; anything else fails fast at broker startup.
Source
Thrown at pulsar-broker-common/src/main/java/org/apache/pulsar/broker/validator/BindAddressValidator.java:75
* @param schemes a filter on the schemes of the bind addresses, or null to not apply a filter.
* @return a list of bind addresses.
*/
public static List<BindAddress> validateBindAddresses(ServiceConfiguration config, Collection<String> schemes) {
String internalListenerName = StringUtils.defaultIfBlank(config.getInternalListenerName(),
ServiceConfiguration.DEFAULT_INTERNAL_LISTENER_NAME);
// migrate the legacy port-based configuration to bind addresses tagged with the internal listener name
List<BindAddress> addresses = migrateBindAddresses(config, internalListenerName);
// parse the list of additional bind addresses; trim whitespace around the comma-separated
// entries so configurations split across multiple lines or padded for readability are accepted
Arrays.stream(StringUtils.split(StringUtils.defaultString(config.getBindAddresses()), ","))
.map(StringUtils::trim)
.filter(StringUtils::isNotEmpty)
.map(s -> {
Matcher m = BIND_ADDRESSES_PATTERN.matcher(s);
if (!m.matches()) {
throw new IllegalArgumentException("bindAddresses: malformed: " + s);
}
return m;
})
.map(m -> {
String name = StringUtils.trim(m.group("name"));
MultipleListenerValidator.validateListenerName(name);
return new BindAddress(name, URI.create(StringUtils.trim(m.group("url"))));
})
.forEach(addresses::add);
// apply the filter
if (schemes != null) {
addresses.removeIf(a -> !schemes.contains(a.getAddress().getScheme()));
}
// Deduplicate by full URI (scheme + ip + port). Tolerate exact duplicates (same URI and
// same listener name) so that a user's bindAddresses entry that matches a migrated binding
// is accepted; reject same URI assigned to different listener names.View on GitHub (pinned to 820761864e)
Solutions
- Rewrite each entry as <listenerName>:<scheme>://<host>:<port>, e.g. internal:pulsar://0.0.0.0:6650
- Verify the listener name contains only ASCII letters, digits, underscore, hyphen
- Check the pattern with a quick regex test before restarting
- Remove empty/stray segments or extra commas from the comma-separated list
Example fix
// before (broker.conf) bindAddresses=pulsar://0.0.0.0:6650,pulsar+ssl://0.0.0.0:6651 // after bindAddresses=internal:pulsar://0.0.0.0:6650,internalsecure:pulsar+ssl://0.0.0.0:6651
Defensive patterns
Strategy: validation
Validate before calling
for (String s : bindAddresses.split(",")) {
s = s.trim();
if (!s.isEmpty() && !s.matches("[A-Za-z0-9_-]+:[a-zA-Z+.-]+://[^:/]+:[0-9]+")) {
throw new IllegalArgumentException("Malformed bindAddresses entry: " + s);
}
} Prevention
- Always use <listenerName>:<scheme>://<host>:<port> for each entry
- Keep listener names to [A-Za-z0-9_-]
- Avoid stray spaces/empty segments in the comma list
- Validate broker.conf with the project's config-check tooling before restart
When it happens
Trigger: Configuring bindAddresses with an entry lacking the listener-name prefix (e.g. just pulsar://0.0.0.0:6650), missing scheme, missing port, containing unescaped commas/spaces that break segmentation, or using a name with invalid characters rejected by MultipleListenerValidator.validateListenerName.
Common situations: Migrating from the legacy bindAddress field to multi-listener bindAddresses and forgetting the 'name:' prefix; typos like double colons or omitting the scheme; copying advertisedListeners-style URLs into bindAddresses; whitespace after commas in multi-value configs.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- bindAddresses: conflicting listener names for ${address}: `$
- the `advertisedListeners` configuration does not contain an
- 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/b149ef3c9a355eb3.
Report an issue: GitHub.