{"record":{"id":"62bef7ff336a06d6","repo":"apache/pulsar","slug":"httpreverseproxy-s-path-must-be-specified-exactly","errorCode":null,"errorMessage":"httpReverseProxy.%s.path must be specified exactly once","messagePattern":"httpReverseProxy\\.(.+?)\\.path must be specified exactly once","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"pulsar-proxy/src/main/java/org/apache/pulsar/proxy/server/ProxyConfiguration.java","lineNumber":1116,"sourceCode":"    public Optional<Integer> getWebServicePortTls() {\n        return webServicePortTls;\n    }\n\n    public void setProperties(Properties properties) {\n        this.properties = properties;\n\n        Map<String, Map<String, String>> redirects = new HashMap<>();\n        Pattern redirectPattern = Pattern.compile(\"^httpReverseProxy\\\\.([^\\\\.]*)\\\\.(.+)$\");\n        Map<String, List<Matcher>> groups = properties.stringPropertyNames().stream()\n            .map((s) -> redirectPattern.matcher(s))\n            .filter(Matcher::matches)\n            .collect(Collectors.groupingBy((m) -> m.group(1))); // group by name\n\n        groups.entrySet().forEach((e) -> {\n                Map<String, String> keyToFullKey = e.getValue().stream().collect(\n                        Collectors.toMap(m -> m.group(2), m -> m.group(0)));\n                if (!keyToFullKey.containsKey(\"path\")) {\n                    throw new IllegalArgumentException(\n                            String.format(\"httpReverseProxy.%s.path must be specified exactly once\", e.getKey()));\n                }\n                if (!keyToFullKey.containsKey(\"proxyTo\")) {\n                    throw new IllegalArgumentException(\n                            String.format(\"httpReverseProxy.%s.proxyTo must be specified exactly once\", e.getKey()));\n                }\n                httpReverseProxyConfigs.add(new HttpReverseProxyConfig(e.getKey(),\n                                                    properties.getProperty(keyToFullKey.get(\"path\")),\n                                                    properties.getProperty(keyToFullKey.get(\"proxyTo\"))));\n            });\n    }\n\n    public static class HttpReverseProxyConfig {\n        private final String name;\n        private final String path;\n        private final String proxyTo;\n\n        HttpReverseProxyConfig(String name, String path, String proxyTo) {","sourceCodeStart":1098,"sourceCodeEnd":1134,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-proxy/src/main/java/org/apache/pulsar/proxy/server/ProxyConfiguration.java#L1098-L1134","documentation":"During ProxyConfiguration validation, httpReverseProxy properties are grouped by their logical name; each group must contain exactly one 'path' (and 'proxyTo') key. If a named reverse-proxy group lacks a 'path' property the configuration is rejected with this IllegalArgumentException.","triggerScenarios":"Proxy startup with properties like httpReverseProxy.myapp.proxyTo set but no corresponding httpReverseProxy.myapp.path — the regex-based grouping finds the group but the required key is missing.","commonSituations":"Copy-pasting a reverse-proxy config block and deleting the path line; renaming the group in one line but not the other so a group is left with only proxyTo; typos like 'paths' or 'Path'.","solutions":["Add the missing httpReverseProxy.<name>.path property for the group named in the message","Also confirm httpReverseProxy.<name>.proxyTo is present, or the sibling error will fire next","Check for group-name typos that split one logical proxy into two partial groups","Restart the proxy and verify the reverse proxy route registers"],"exampleFix":"// before\nhttpReverseProxy.myapp.proxyTo=http://localhost:8080\n// after\nhttpReverseProxy.myapp.path=/myapp\nhttpReverseProxy.myapp.proxyTo=http://localhost:8080","handlingStrategy":"validation","validationCode":"// Pre-validate reverse proxy config groups\nMap<String, Set<String>> groups = groupHttpReverseProxyKeys(properties);\nfor (var e : groups.entrySet()) {\n    if (!e.getValue().contains(\"path\")) throw new IllegalStateException(\"httpReverseProxy.\" + e.getKey() + \".path must be specified exactly once\");\n    if (!e.getValue().contains(\"proxyTo\")) throw new IllegalStateException(\"httpReverseProxy.\" + e.getKey() + \".proxyTo must be specified exactly once\");\n}","typeGuard":null,"tryCatchPattern":"try { conf.validate(); } catch (IllegalArgumentException e) { if (e.getMessage().contains(\"httpReverseProxy\")) log.error(\"Incomplete reverse-proxy group: {}\", e.getMessage()); throw e; }","preventionTips":["Treat each httpReverseProxy.<name>.* block as atomic: always set path and proxyTo together","Lint proxy properties in CI for required reverse-proxy pairs before deployment"],"tags":["configuration","validation","http-reverse-proxy","pulsar-proxy"],"backgroundTag":"missing-required-config-property","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"}