eclipse-vertx/vert.x · error · IllegalArgumentException
Scheme:
Error message
Scheme:
What it means
WebSocketClientImpl.webSocketConnectOptionsAbs parses a WebSocket URL passed to the client and requires its scheme to be exactly ws or wss. If the URI's scheme is anything else (http, https, missing scheme, or a typo), it throws IllegalArgumentException("Scheme: " + scheme) so the connect request never proceeds with a non-WebSocket endpoint.
Source
Thrown at vertx-core/src/main/java/io/vertx/core/http/impl/WebSocketClientImpl.java:149
public Future<WebSocket> webSocket(int port, String host, String requestURI) {
return webSocket(new WebSocketConnectOptions().setURI(requestURI).setHost(host).setPort(port));
}
public Future<WebSocket> webSocket(WebSocketConnectOptions options) {
return webSocket(vertx.getOrCreateContext(), options);
}
static WebSocketConnectOptions webSocketConnectOptionsAbs(String url, MultiMap headers, WebSocketVersion version, List<String> subProtocols) {
URI uri;
try {
uri = new URI(url);
} catch (URISyntaxException e) {
throw new IllegalArgumentException(e);
}
String scheme = uri.getScheme();
if (!"ws".equals(scheme) && !"wss".equals(scheme)) {
throw new IllegalArgumentException("Scheme: " + scheme);
}
boolean ssl = scheme.length() == 3;
int port = uri.getPort();
if (port == -1) port = ssl ? 443 : 80;
StringBuilder relativeUri = new StringBuilder();
if (uri.getRawPath() != null) {
relativeUri.append(uri.getRawPath());
}
if (uri.getRawQuery() != null) {
relativeUri.append('?').append(uri.getRawQuery());
}
if (uri.getRawFragment() != null) {
relativeUri.append('#').append(uri.getRawFragment());
}
return new WebSocketConnectOptions()
.setHost(uri.getHost())
.setPort(port).setSsl(ssl)
.setURI(relativeUri.toString())View on GitHub (pinned to fb308bd8c3)
Solutions
- Change the URL to use the ws:// or wss:// scheme (wss for TLS, which also selects port 443/SSL)
- If you only have an http(s) URL, derive the scheme: http->ws, https->wss
- Trim whitespace and validate the URL before passing it to webSocket()
- Prefer passing WebSocketConnectOptions with explicit host/port/ssl/uri instead of a raw URL string
Example fix
// before
client.webSocket("https://example.com/events", ws -> {...});
// after
client.webSocket("wss://example.com/events", ws -> {...}); Defensive patterns
Strategy: validation
Validate before calling
static boolean isValidWsUrl(String url) {
try {
java.net.URI u = new java.net.URI(url);
return "ws".equals(u.getScheme()) || "wss".equals(u.getScheme());
} catch (URISyntaxException e) { return false; }
} Try / catch
try {
client.webSocket(url, ws -> {...});
} catch (IllegalArgumentException e) {
if (e.getMessage() != null && e.getMessage().startsWith("Scheme:")) {
throw new IllegalArgumentException("URL must use ws:// or wss://: " + url, e);
}
throw e;
} Prevention
- Store WebSocket endpoints with explicit ws:// or wss:// schemes in configuration
- Convert http(s) endpoints to ws(s) programmatically instead of hand-editing URLs
- Trim and validate all endpoint URLs loaded from env vars/properties
- Prefer WebSocketConnectOptions with explicit setSsl/setHost/setPort/setURI over raw URL strings
When it happens
Trigger: Calling webSocket()/webSocketAbs with a URL like "http://host/sock", "//host/path", "host:9999/path" (no scheme, so uri.getScheme() is the hostname or null), or "WS://host" (case-sensitive comparison fails only if server-side, but here scheme is lowercased by URI parsing, so mostly wrong scheme or missing scheme).
Common situations: Config value taken from an environment variable or property meant for an HTTP URL reused for WebSockets; users forgetting to swap http->ws or https->wss; URLs built by string concatenation that omit the scheme; trailing/leading whitespace producing a null or mangled scheme.
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
- Scheme:
- Invalid url:
- maxWebSockets must be > 0 or -1 (disabled)
- Multipart form requires multipart/form-data content type ins
- Sending form requires multipart/form-data or " + HttpHeaders
AI-assisted analysis of eclipse-vertx/vert.x@fb308bd8c3 (2026-09-06).
Data as JSON: /api/errors/b5519cc4d418a657.
Report an issue: GitHub.