{"record":{"id":"b149ef3c9a355eb3","repo":"apache/pulsar","slug":"bindaddresses-malformed-address","errorCode":null,"errorMessage":"bindAddresses: malformed: ${address}","messagePattern":"bindAddresses: malformed: (.+?)","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"pulsar-broker-common/src/main/java/org/apache/pulsar/broker/validator/BindAddressValidator.java","lineNumber":75,"sourceCode":"     * @param schemes a filter on the schemes of the bind addresses, or null to not apply a filter.\n     * @return a list of bind addresses.\n     */\n    public static List<BindAddress> validateBindAddresses(ServiceConfiguration config, Collection<String> schemes) {\n        String internalListenerName = StringUtils.defaultIfBlank(config.getInternalListenerName(),\n                ServiceConfiguration.DEFAULT_INTERNAL_LISTENER_NAME);\n\n        // migrate the legacy port-based configuration to bind addresses tagged with the internal listener name\n        List<BindAddress> addresses = migrateBindAddresses(config, internalListenerName);\n\n        // parse the list of additional bind addresses; trim whitespace around the comma-separated\n        // entries so configurations split across multiple lines or padded for readability are accepted\n        Arrays.stream(StringUtils.split(StringUtils.defaultString(config.getBindAddresses()), \",\"))\n                .map(StringUtils::trim)\n                .filter(StringUtils::isNotEmpty)\n                .map(s -> {\n                    Matcher m = BIND_ADDRESSES_PATTERN.matcher(s);\n                    if (!m.matches()) {\n                        throw new IllegalArgumentException(\"bindAddresses: malformed: \" + s);\n                    }\n                    return m;\n                })\n                .map(m -> {\n                    String name = StringUtils.trim(m.group(\"name\"));\n                    MultipleListenerValidator.validateListenerName(name);\n                    return new BindAddress(name, URI.create(StringUtils.trim(m.group(\"url\"))));\n                })\n                .forEach(addresses::add);\n\n        // apply the filter\n        if (schemes != null) {\n            addresses.removeIf(a -> !schemes.contains(a.getAddress().getScheme()));\n        }\n\n        // Deduplicate by full URI (scheme + ip + port). Tolerate exact duplicates (same URI and\n        // same listener name) so that a user's bindAddresses entry that matches a migrated binding\n        // is accepted; reject same URI assigned to different listener names.","sourceCodeStart":57,"sourceCodeEnd":93,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-broker-common/src/main/java/org/apache/pulsar/broker/validator/BindAddressValidator.java#L57-L93","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before (broker.conf)\nbindAddresses=pulsar://0.0.0.0:6650,pulsar+ssl://0.0.0.0:6651\n// after\nbindAddresses=internal:pulsar://0.0.0.0:6650,internalsecure:pulsar+ssl://0.0.0.0:6651","handlingStrategy":"validation","validationCode":"for (String s : bindAddresses.split(\",\")) {\n    s = s.trim();\n    if (!s.isEmpty() && !s.matches(\"[A-Za-z0-9_-]+:[a-zA-Z+.-]+://[^:/]+:[0-9]+\")) {\n        throw new IllegalArgumentException(\"Malformed bindAddresses entry: \" + s);\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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"],"tags":["configuration","bind-address","multi-listener","broker"],"backgroundTag":"invalid-bind-address-format","analyzedSha":"820761864ed8e2a7d2e52dd9763ad2ae117c1395","analyzedAt":"2026-09-06T00:14:20.138Z","contentChangedAt":"2026-09-06T00:14:20.138Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}