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
- Set the transport URL to a full absolute HTTP(S) URL, e.g. https://host.example.com:8080/mcp, with a scheme and hostname.
- URL-encode any special characters in the path or query so URI parsing succeeds.
- 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
- Always include scheme and host in transport URLs (https://host/path)
- Run --validate-only in CI on every metadata change
- Leave the url field absent for stdio transports
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.