{"record":{"id":"9b29c75776665711","repo":"apache/pulsar","slug":"host-must-not-be-null","errorCode":null,"errorMessage":"host must not be null","messagePattern":"host must not be null","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"pulsar-broker-common/src/main/java/org/apache/pulsar/broker/validator/MultipleListenerValidator.java","lineNumber":52,"sourceCode":"\n/**\n * Validates multiple listener address configurations.\n */\npublic final class MultipleListenerValidator {\n\n    /** Allowed listener-name characters: ASCII letters, digits, underscore, hyphen. */\n    private static final Pattern LISTENER_NAME_PATTERN = Pattern.compile(\"[A-Za-z0-9_-]+\");\n\n    /**\n     * Format the host:port part of a URI for use as a uniqueness key and in error messages, wrapping\n     * IPv6 literals in brackets so that the colon separator is unambiguous. {@link URI#getHost()} may\n     * or may not include the brackets depending on the JDK, so they are stripped before the\n     * {@link NetUtil#isValidIpV6Address} check.\n     */\n    static String formatHostPort(URI uri) {\n        String host = uri.getHost();\n        if (host == null) {\n            throw new IllegalArgumentException(\"host must not be null\");\n        }\n        String unbracketed = host.startsWith(\"[\") && host.endsWith(\"]\")\n                ? host.substring(1, host.length() - 1) : host;\n        if (NetUtil.isValidIpV6Address(unbracketed)) {\n            return \"[\" + unbracketed + \"]:\" + uri.getPort();\n        }\n        return host + \":\" + uri.getPort();\n    }\n\n    /**\n     * Validate a listener name. Listener names must be non-blank and contain only ASCII letters,\n     * digits, underscore, and hyphen so they are safe to embed in URLs without encoding.\n     *\n     * @throws IllegalArgumentException if the name is null, blank, or contains disallowed characters.\n     */\n    public static void validateListenerName(String name) {\n        if (StringUtils.isBlank(name)) {\n            throw new IllegalArgumentException(\"listener name must not be blank\");","sourceCodeStart":34,"sourceCodeEnd":70,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-broker-common/src/main/java/org/apache/pulsar/broker/validator/MultipleListenerValidator.java#L34-L70","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Always include an explicit host in listener URLs; bracket IPv6 addresses: pulsar://[fe80::1]:6650","Check the URL with new URI(s) and assert getHost() != null before passing it in","Remove illegal characters from the hostname","If constructing URIs programmatically, use URI(scheme, host, port, ...) so the host is encoded correctly"],"exampleFix":"// before\nString url = \"pulsar://fe80::1:6650\"; // getHost() == null\n// after\nString url = \"pulsar://[fe80::1]:6650\"; // getHost() == \"fe80::1\"","handlingStrategy":"validation","validationCode":"static boolean hasHost(String listenerUrl) {\n    try {\n        URI uri = URI.create(listenerUrl);\n        return uri.getHost() != null && !uri.getHost().isEmpty();\n    } catch (IllegalArgumentException e) {\n        return false;\n    }\n}","typeGuard":"static boolean isParseableListenerUri(URI uri) {\n    return uri != null && uri.getHost() != null;\n}","tryCatchPattern":null,"preventionTips":["Bracket IPv6 literals: pulsar://[::1]:6650","Never omit the host part of listener URLs","Test URIs with new URI(...).getHost() before configuring","Reject configs whose listener URL fails URI parsing in CI"],"tags":["uri","ipv6","configuration","multi-listener"],"backgroundTag":"invalid-listener-url","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"}