{"record":{"id":"52f1b546249f14b6","repo":"apache/shenyu","slug":"invalid-upstream-url-expected-host-port-format-but-was","errorCode":null,"errorMessage":"Invalid upstream URL, expected 'host:port' format but was: ","messagePattern":"Invalid upstream URL, expected 'host:port' format but was: ","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"shenyu-admin/src/main/java/org/apache/shenyu/admin/transfer/DiscoveryTransfer.java","lineNumber":356,"sourceCode":"            discoveryUpstreamDTO.setDateCreated(data.getDateCreated());\n            discoveryUpstreamDTO.setDateUpdated(data.getDateUpdated());\n            return discoveryUpstreamDTO;\n        }).orElse(null);\n    }\n\n    /**\n     * mapToDiscoveryUpstreamData.\n     *\n     * @param commonUpstream commonUpstream\n     * @return DiscoveryUpstreamData\n     */\n    public DiscoveryUpstreamData mapToDiscoveryUpstreamData(CommonUpstream commonUpstream) {\n        String upstreamUrl = commonUpstream.getUpstreamUrl();\n        String[] parts = Optional.ofNullable(upstreamUrl)\n                .map(url -> url.split(\":\", 2))\n                .orElseThrow(() -> new IllegalArgumentException(\"Upstream URL must not be null\"));\n        if (parts.length < 2) {\n            throw new IllegalArgumentException(\"Invalid upstream URL, expected 'host:port' format but was: \" + upstreamUrl);\n        }\n        String host = parts[0];\n        int port;\n        try {\n            port = Integer.parseInt(parts[1]);\n        } catch (NumberFormatException ex) {\n            throw new IllegalArgumentException(\"Invalid port in upstream URL: \" + upstreamUrl, ex);\n        }\n        DiscoveryUpstreamDTO discoveryUpstreamDTO = CommonUpstreamUtils.buildDefaultDiscoveryUpstreamDTO(\n                host,\n                port,\n                commonUpstream.getProtocol(),\n                commonUpstream.getNamespaceId());\n        Properties properties = Optional.ofNullable(discoveryUpstreamDTO.getProps())\n                .map(props -> GsonUtils.getInstance().fromJson(props, Properties.class))\n                .orElse(new Properties());\n        properties.setProperty(\"healthCheckEnabled\", String.valueOf(commonUpstream.isHealthCheckEnabled()));\n        discoveryUpstreamDTO.setProps(GsonUtils.getInstance().toJson(properties));","sourceCodeStart":338,"sourceCodeEnd":374,"githubUrl":"https://github.com/apache/shenyu/blob/567142e07261b3e615ae8850b30f4421f455cc5d/shenyu-admin/src/main/java/org/apache/shenyu/admin/transfer/DiscoveryTransfer.java#L338-L374","documentation":"DiscoveryTransfer.mapToDiscoveryUpstreamData converts a CommonUpstream into DiscoveryUpstreamData and requires upstreamUrl in 'host:port' form. Splitting on ':' must yield at least 2 parts; if it doesn't (no colon or null already handled earlier), IllegalArgumentException is thrown.","triggerScenarios":"A discovery upstream URL registered without a port — e.g. 'myhost' or 'http://myhost' style URLs where the split on ':' (limit 2) produces fewer than 2 parts — reaches mapToDiscoveryUpstreamData during discovery config sync/transfer.","commonSituations":"Registering backend instances without explicit ports in the dashboard or via client auto-registration; zookeeper/nacos/etcd discovery nodes storing bare hostnames; IPv6 addresses (multiple colons) breaking the naive split; upstream entries created before a format change in a newer ShenYu version.","solutions":["Register the upstream with an explicit 'host:port' URL, e.g. '192.168.1.10:8080'","Fix the source discovery data (nacos/zk/etcd instance metadata) to include the port","If using IPv6, wrap the address in brackets with the port: '[::1]:8080' or pre-normalize before transfer","Inspect CommonUpstream producers to ensure they always populate a port-bearing upstreamUrl"],"exampleFix":"// before\ncommonUpstream.setUpstreamUrl(\"my-service\");\n// after\ncommonUpstream.setUpstreamUrl(\"my-service:8080\");","handlingStrategy":"validation","validationCode":"boolean validUpstream = url != null && url.matches(\"[^:]+:\\\\d{1,5}\");","typeGuard":"boolean isHostPort(String url) { int i = url.indexOf(':'); return i > 0 && i < url.length() - 1 && url.substring(i + 1).chars().allMatch(Character::isDigit); }","tryCatchPattern":"try { transfer.mapToDiscoveryUpstreamData(upstream); } catch (IllegalArgumentException e) { log.error(\"bad upstream {}\", upstream.getUpstreamUrl(), e); skipEntry(); }","preventionTips":["Always register upstreams with explicit numeric ports","Validate the host:port form in dashboard forms and registration APIs","Normalize full URLs (strip scheme/path) before storing upstreamUrl","Bracket IPv6 hosts: '[::1]:8080'"],"tags":["discovery","url-format","upstream","admin"],"backgroundTag":"invalid-url-format","analyzedSha":"567142e07261b3e615ae8850b30f4421f455cc5d","analyzedAt":"2026-09-12T10:08:21.293Z","contentChangedAt":"2026-09-12T10:08:21.293Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}