eclipse-vertx/vert.x · error · WebSocketHandshakeException
Invalid HTTP method
Error message
Invalid HTTP method
What it means
This WebSocketHandshakeException is thrown in createHandshaker when the WebSocket upgrade request uses an HTTP method other than GET. RFC 6455 mandates that the opening handshake be a GET request. Vert.x responds with 405 Method Not Allowed and aborts the handshake.
Source
Thrown at vertx-core/src/main/java/io/vertx/core/http/impl/http1/Http1ServerConnection.java:381
});
}
public WebSocketServerHandshaker createHandshaker(Http1ServerRequest request) throws WebSocketHandshakeException {
// As a fun part, Firefox 6.0.2 supports Websockets protocol '7'. But,
// it doesn't send a normal 'Connection: Upgrade' header. Instead it
// sends: 'Connection: keep-alive, Upgrade'. Brilliant.
String connectionHeader = request.getHeader(io.vertx.core.http.HttpHeaders.CONNECTION);
if (connectionHeader == null || !connectionHeader.toLowerCase().contains("upgrade")) {
request.response()
.setStatusCode(BAD_REQUEST.code())
.end("\"Connection\" header must be \"Upgrade\".");
throw new WebSocketHandshakeException("Invalid connection header");
}
if (request.method() != io.vertx.core.http.HttpMethod.GET) {
request.response()
.setStatusCode(METHOD_NOT_ALLOWED.code())
.end();
throw new WebSocketHandshakeException("Invalid HTTP method");
}
String wsURL;
try {
wsURL = HttpUtils.getWebSocketLocation(request, isSsl());
} catch (Exception e) {
request.response()
.setStatusCode(BAD_REQUEST.code())
.end("Invalid request URI");
throw new WebSocketHandshakeException("Invalid WebSocket location", e);
}
String subProtocols = null;
if (webSocketConfig.getSubProtocols() != null) {
subProtocols = String.join(",", webSocketConfig.getSubProtocols());
}
WebSocketDecoderConfig config = WebSocketDecoderConfig.newBuilder()
.allowExtensions(webSocketConfig.getUsePerMessageCompression() || webSocketConfig.getUsePerFrameCompression())
.maxFramePayloadLength(webSocketConfig.getMaxFrameSize())
.allowMaskMismatch(webSocketConfig.isUseUnmaskedFrames())View on GitHub (pinned to fb308bd8c3)
Solutions
- Send the WebSocket handshake as an HTTP GET request.
- Fix client library configuration that overrides the handshake method.
- Route non-GET traffic away from the WebSocket endpoint so it never reaches the upgrade handler.
- If you need both REST and WebSocket on one URL, branch on request.method() before upgrading.
Example fix
// before
httpClient.request(HttpMethod.POST, "/ws")
.compose(req -> req.send());
// after (WebSocket handshake must be GET)
client.webSocket("/ws"); Defensive patterns
Strategy: validation
Validate before calling
if (request.method() != HttpMethod.GET) {
// WebSocket handshake must be GET; reject early
} Try / catch
try {
serverRequest.toWebSocket();
} catch (WebSocketHandshakeException e) {
respondMethodNotAllowed(e);
} Prevention
- WebSocket handshakes are always GET per RFC 6455
- Keep REST routes separate from WebSocket upgrade routes
- Audit test suites hitting the WS endpoint with POST
When it happens
Trigger: Issuing POST/PUT/DELETE (or any non-GET) request to a WebSocket endpoint and then calling the server-side upgrade path (createHandshaker, invoked from createWebSocket).
Common situations: Posting JSON to a URL that also serves WebSocket upgrades; misconfigured client libraries using POST; load tests sending POST requests to a websocket route.
Understand the failure class
Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.
Related errors
- Invalid connection header
- Invalid WebSocket location
- Invalid WebSocket version
- Protocol version ${version} not supported.
- maxWebSockets must be > 0 or -1 (disabled)
AI-assisted analysis of eclipse-vertx/vert.x@fb308bd8c3 (2026-09-06).
Data as JSON: /api/errors/ed13e8f6603036c1.
Report an issue: GitHub.