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

  1. Check the server response (curl -i with Upgrade headers) to see the actual status code and fix the URL/path or server config
  2. Ensure the server endpoint actually performs the WebSocket upgrade (correct library/route enabled)
  3. Verify any reverse proxy (nginx/HAProxy/Apache) forwards Upgrade and Connection headers
  4. Add required auth headers via custom Draft/headers (e.g. via WebSocketClient constructor with HttpHeaders) so the server does not return 401/403
  5. 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

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


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)