TooTallNate/Java-WebSocket · error · InvalidHandshakeException
Invalid status code received
Error message
Invalid status code received: %s Status line: %s
What it means
During the WebSocket client handshake, translateHandshakeHttpClient parses the HTTP status line returned by the server. The WebSocket protocol requires the server to reply with HTTP 101 Switching Protocols; any other status code makes Draft throw InvalidHandshakeException with this message, so the connection is rejected before it becomes a WebSocket.
Solutions
- Check the server response (curl -i with Upgrade headers) to see the actual status code and fix the URL/path or server config
- Ensure the server endpoint actually performs the WebSocket upgrade (correct library/route enabled)
- Verify any reverse proxy (nginx/HAProxy/Apache) forwards Upgrade and Connection headers
- Add required auth headers via custom Draft/headers (e.g. via WebSocketClient constructor with HttpHeaders) so the server does not return 401/403
- Retry against the correct port and scheme (ws vs wss)
Example fix
// before (server returns 404)
WebSocketClient ws = new WebSocketClient(new URI("ws://host/api/wrong-path"));
// after
WebSocketClient ws = new WebSocketClient(new URI("ws://host/ws/chat"), new Draft_6455()); Defensive patterns
Strategy: validation
Validate before calling
// client side: verify endpoint does the upgrade before connecting
HttpURLConnection c = (HttpURLConnection) new URL("http://host/ws/chat").openConnection();
c.setRequestProperty("Upgrade", "websocket");
c.setRequestProperty("Connection", "Upgrade");
c.setRequestProperty("Sec-WebSocket-Key", "dGhlIHNhbXBsZSBub25jZQ==");
c.setRequestProperty("Sec-WebSocket-Version", "13");
int status = c.getResponseCode();
if (status != 101) throw new IllegalStateException("Endpoint returned HTTP " + status + ", not 101"); Try / catch
try {
client.connectBlocking();
} catch (WebSocketClient.WebSocketClientException | InterruptedException e) {
// InvalidHandshakeException: inspect server HTTP status / auth / proxy
logger.error("WS handshake rejected: {}", e.getMessage());
} Prevention
- Confirm the endpoint path/port serves WebSocket upgrades
- Configure proxies to pass through Upgrade/Connection headers
- Attach auth headers so the server never answers 401/403 to the handshake
- Test with curl -i using upgrade headers first
When it happens
Trigger: Connecting to a server that answers the upgrade request with a non-101 response, e.g. wscat/websocket-client against an endpoint returning 200 OK, 404 Not Found (wrong path), 401/403 (auth failure), 400, or a proxy error page.
Common situations: Wrong WebSocket endpoint URL/path, server not supporting WebSocket on that port, reverse proxy or load balancer intercepting the Upgrade request, missing auth headers causing 401, hitting a plain HTTP endpoint instead of a WS endpoint, server rejecting due to missing Origin or subprotocol mismatch.
Related errors
- unknown role
- missing Sec-WebSocket-Key
- http resource descriptor must not be null
- buffer size < 0
- parameter must not be null
AI-assisted analysis of TooTallNate/Java-WebSocket@afeacbf8c0 (2026-09-09).
Data as JSON: /api/errors/484c1e0aecea266f.
Report an issue: GitHub.
Appendix: source
Thrown at src/main/java/org/java_websocket/drafts/Draft.java:168
.format("Invalid status line received: %s Status line: %s", firstLineTokens[2], line));
}
ClientHandshakeBuilder clienthandshake = new HandshakeImpl1Client();
clienthandshake.setResourceDescriptor(firstLineTokens[1]);
return clienthandshake;
}
/**
* Checking the handshake for the role as client
*
* @param firstLineTokens the token of the first line split as as an string array
* @param line the whole line
* @return a handshake
*/
private static HandshakeBuilder translateHandshakeHttpClient(String[] firstLineTokens,
String line) throws InvalidHandshakeException {
// translating/parsing the response from the SERVER
if (!"101".equals(firstLineTokens[1])) {
throw new InvalidHandshakeException(String
.format("Invalid status code received: %s Status line: %s", firstLineTokens[1], line));
}
if (!"HTTP/1.1".equalsIgnoreCase(firstLineTokens[0])) {
throw new InvalidHandshakeException(String
.format("Invalid status line received: %s Status line: %s", firstLineTokens[0], line));
}
HandshakeBuilder handshake = new HandshakeImpl1Server();
ServerHandshakeBuilder serverhandshake = (ServerHandshakeBuilder) handshake;
serverhandshake.setHttpStatus(Short.parseShort(firstLineTokens[1]));
serverhandshake.setHttpStatusMessage(firstLineTokens[2]);
return handshake;
}
public abstract HandshakeState acceptHandshakeAsClient(ClientHandshake request,
ServerHandshake response) throws InvalidHandshakeException;
public abstract HandshakeState acceptHandshakeAsServer(ClientHandshake handshakedata)
throws InvalidHandshakeException;View on GitHub (pinned to afeacbf8c0)