apache/shenyu · error · IllegalArgumentException

Invalid port in upstream URL:

Error message

Invalid port in upstream URL: 

What it means

In mapToDiscoveryUpstreamData, the part after the first ':' in upstreamUrl is parsed as an integer port; NumberFormatException is wrapped into IllegalArgumentException('Invalid port in upstream URL: ...').

Solutions

  1. Store the upstream as plain 'host:port' with a numeric port, e.g. '10.0.0.5:8080' — not a full URL
  2. Fix the offending entry in the dashboard discovery upstream list or in the discovery center data
  3. Strip scheme/path before registering upstreams obtained from service registries
  4. Add input validation in the dashboard form/API when creating upstreams

Example fix

// before
upstreamUrl = "http://10.0.0.5:8080/api";
// after
upstreamUrl = "10.0.0.5:8080";
Defensive patterns

Strategy: validation

Validate before calling

int port = -1;
String p = url.substring(url.indexOf(':') + 1);
boolean portOk = p.chars().allMatch(Character::isDigit) && !p.isEmpty();
if (portOk) port = Integer.parseInt(p);

Try / catch

try { map(u); } catch (IllegalArgumentException e) { log.warn("invalid port for {}", u.getUpstreamUrl()); sanitizeAndRetry(); }

Prevention

When it happens

Trigger: URL like 'host:abc', 'host:' (empty port), or 'host:8080x' reaches the transfer; also URLs where the remainder after ':' is not purely numeric, e.g. 'http://host:8080/path' (split limit 2 leaves '//host:8080/path' as the second part... actually 'http' + '//host:8080/path') making port parsing fail.

Common situations: Users entering full URLs (http://host:8080) instead of host:port in discovery config; trailing slashes/paths on upstream entries; typo'd ports; copy-paste of service URIs from other tools.

Understand the failure class

Background: "Invalid URL" errors: why new URL(), URI.parse, and reqwest::Url reject your string — missing scheme, whitespace, and bad path format — this error's family across 39 libraries.

Related errors


AI-assisted analysis of apache/shenyu@567142e072 (2026-09-12). Data as JSON: /api/errors/2e82f31a4316f0c7. Report an issue: GitHub.

Appendix: source

Thrown at shenyu-admin/src/main/java/org/apache/shenyu/admin/transfer/DiscoveryTransfer.java:363

     * mapToDiscoveryUpstreamData.
     *
     * @param commonUpstream commonUpstream
     * @return DiscoveryUpstreamData
     */
    public DiscoveryUpstreamData mapToDiscoveryUpstreamData(CommonUpstream commonUpstream) {
        String upstreamUrl = commonUpstream.getUpstreamUrl();
        String[] parts = Optional.ofNullable(upstreamUrl)
                .map(url -> url.split(":", 2))
                .orElseThrow(() -> new IllegalArgumentException("Upstream URL must not be null"));
        if (parts.length < 2) {
            throw new IllegalArgumentException("Invalid upstream URL, expected 'host:port' format but was: " + upstreamUrl);
        }
        String host = parts[0];
        int port;
        try {
            port = Integer.parseInt(parts[1]);
        } catch (NumberFormatException ex) {
            throw new IllegalArgumentException("Invalid port in upstream URL: " + upstreamUrl, ex);
        }
        DiscoveryUpstreamDTO discoveryUpstreamDTO = CommonUpstreamUtils.buildDefaultDiscoveryUpstreamDTO(
                host,
                port,
                commonUpstream.getProtocol(),
                commonUpstream.getNamespaceId());
        Properties properties = Optional.ofNullable(discoveryUpstreamDTO.getProps())
                .map(props -> GsonUtils.getInstance().fromJson(props, Properties.class))
                .orElse(new Properties());
        properties.setProperty("healthCheckEnabled", String.valueOf(commonUpstream.isHealthCheckEnabled()));
        discoveryUpstreamDTO.setProps(GsonUtils.getInstance().toJson(properties));
        return mapToData(discoveryUpstreamDTO);
    }
}

View on GitHub (pinned to 567142e072)