apache/shardingsphere · error · IllegalArgumentException

streamable-http transport URL must be an HTTP URL.

Error message

streamable-http transport URL must be an HTTP URL.

What it means

Thrown by MCPRegistryMetadataCommand.validateHttpUrl while validating registry metadata: the streamable-http transport entry has a URL, but it is not parseable as a URI with an http or https scheme and a non-null host. Non-HTTP schemes (file:, tcp:), missing host (bare 'localhost:8080'), and malformed URIs all fail.

Source

Thrown at mcp/registry/src/main/java/org/apache/shardingsphere/mcp/registry/MCPRegistryMetadataCommand.java:249

    private static void validateVersion(final String label, final String value, final boolean allowSnapshot) {
        ShardingSpherePreconditions.checkState(!value.isBlank() && !"null".equals(value), () -> new IllegalArgumentException(label + " must be a non-empty string."));
        ShardingSpherePreconditions.checkState(!"latest".equals(value), () -> new IllegalArgumentException(label + " must not use latest."));
        ShardingSpherePreconditions.checkState(!VERSION_RANGE_PATTERN.matcher(value).matches(),
                () -> new IllegalArgumentException(label + " must be a specific version, not a range."));
        if (!allowSnapshot) {
            ShardingSpherePreconditions.checkState(!value.contains("SNAPSHOT"), () -> new IllegalArgumentException(label + " must not contain SNAPSHOT for publication."));
        }
    }
    
    private static void validateHttpUrl(final Object value) {
        ShardingSpherePreconditions.checkState(value instanceof String && !((String) value).isBlank(),
                () -> new IllegalArgumentException("streamable-http transport must define a URL."));
        try {
            URI uri = new URI((String) value);
            ShardingSpherePreconditions.checkState(("http".equals(uri.getScheme()) || "https".equals(uri.getScheme())) && null != uri.getHost(),
                    () -> new IllegalArgumentException("streamable-http transport URL must be an HTTP URL."));
        } catch (final URISyntaxException ex) {
            throw new IllegalArgumentException("streamable-http transport URL must be an HTTP URL.", ex);
        }
    }
    
    private static void validateEnvironmentVariable(final Map<String, Object> packageMetadata, final String name) {
        Object envVars = packageMetadata.get("environmentVariables");
        ShardingSpherePreconditions.checkState(envVars instanceof List<?>, () -> new IllegalArgumentException("MCP Registry package must define " + name + "."));
        Map<?, ?> envVar = findEnvironmentVariable((List<?>) envVars, name);
        ShardingSpherePreconditions.checkState(Boolean.FALSE.equals(envVar.get("isRequired")),
                () -> new IllegalArgumentException(String.format("MCP Registry metadata for %s must declare isRequired as false.", name)));
        ShardingSpherePreconditions.checkState(Boolean.FALSE.equals(envVar.get("isSecret")),
                () -> new IllegalArgumentException(String.format("MCP Registry metadata for %s must declare isSecret as false.", name)));
        ShardingSpherePreconditions.checkState("string".equals(envVar.get("format")),
                () -> new IllegalArgumentException(String.format("MCP Registry metadata for %s format must be string.", name)));
    }
    
    private static Map<?, ?> findEnvironmentVariable(final List<?> envVars, final String name) {
        return envVars.stream().filter(each -> each instanceof Map<?, ?>).map(each -> (Map<?, ?>) each).filter(each -> name.equals(each.get("name"))).findFirst()
                .orElseThrow(() -> new IllegalArgumentException("MCP Registry package must define " + name + "."));

View on GitHub (pinned to e952770a21)

Solutions

  1. Set the transport URL to a full absolute HTTP(S) URL, e.g. https://host.example.com:8080/mcp, with a scheme and hostname.
  2. URL-encode any special characters in the path or query so URI parsing succeeds.
  3. Run the command with --validate-only before publishing to catch metadata errors early.

Example fix

// before
"url": "localhost:8080/mcp"
// after
"url": "https://localhost:8080/mcp"
Defensive patterns

Strategy: validation

Validate before calling

try {
    URI uri = URI.create((String) transports.get("streamable-http").get("url"));
    if (!("http".equals(uri.getScheme()) || "https".equals(uri.getScheme())) || uri.getHost() == null) throw new IllegalArgumentException("bad url");
} catch (final IllegalArgumentException ex) { /* fix metadata before publishing */ }

Type guard

const isHttpUrl = u => { try { const x = new URL(u); return x.protocol === "http:" || x.protocol === "https:"; } catch { return false; } };

Try / catch

try {
    command.run(args); // include --validate-only
} catch (final IllegalArgumentException ex) {
    // fix the transport url in the registry JSON; rerun with --validate-only until clean
}

Prevention

When it happens

Trigger: Publishing/validating MCP registry metadata where transports[streamable-http].url is e.g. "localhost:8080/mcp" (no scheme), "tcp://host:port", or contains characters that make new URI(...) throw URISyntaxException (spaces, unencoded brackets).

Common situations: Draft registry JSON hand-edited with a scheme-less URL, confusion between the streamable-http and stdio transports (stdio entries must not define a URL), or environment-specific URLs pasted without the https:// prefix.

Related errors


AI-assisted analysis of apache/shardingsphere@e952770a21 (2026-08-14). Data as JSON: /api/errors/07de77763b016035. Report an issue: GitHub.