TooTallNate/Java-WebSocket · error · IllegalArgumentException

unknown role

Error message

unknown role

What it means

Draft.createHandshake serializes a Handshakedata into raw HTTP bytes and needs to know whether it represents a client (GET request) or server (101 response) handshake. If the object is neither a ClientHandshake nor a ServerHandshake, it throws IllegalArgumentException("unknown role").

Solutions

  1. Implement your handshake object as ClientHandshake (client requests) or ServerHandshake (server responses)
  2. Use the library's own HandshakeImpl1Client/HandshakeImpl1Server classes instead of custom implementations
  3. Set the role on the draft (draft.setRole(...)) and let the library construct the handshake

Example fix

// before
Handshakedata hs = new MyHandshake();
draft.createHandshake(hs);
// after
Handshakedata hs = new HandshakeImpl1Client();
draft.createHandshake(hs);
Defensive patterns

Strategy: type-guard

Validate before calling

private static boolean hasKnownRole(Handshakedata hs) {
  return hs instanceof ClientHandshake || hs instanceof ServerHandshake;
}

Type guard

boolean hasKnownRole(Handshakedata hs) {
  return hs instanceof ClientHandshake || hs instanceof ServerHandshake;
}

Try / catch

try {
  draft.createHandshake(handshakedata);
} catch (IllegalArgumentException e) {
  logger.error("Handshake has no client/server role: {}", e.getMessage());
}

Prevention

When it happens

Trigger: Passing a custom or mock Handshake implementation that implements neither ClientHandshake nor ServerHandshake into createHandshake (e.g. in tests or custom draft code).

Common situations: Writing a custom Draft subclass or unit tests with a hand-rolled Handshakedata implementation, refactoring that lost the Client/Server marker interface.

Understand the failure class

Background: "must be a positive integer", "cannot be empty", "invalid argument": how invalid-argument errors work across open-source libraries — this error's family across 33 libraries.

Related errors


AI-assisted analysis of TooTallNate/Java-WebSocket@afeacbf8c0 (2026-09-09). Data as JSON: /api/errors/2607d493e33860a3. Report an issue: GitHub.

Appendix: source

Thrown at src/main/java/org/java_websocket/drafts/Draft.java:272

  /**
   * @deprecated use createHandshake without the role since it does not have any effect
   */
  @Deprecated
  public List<ByteBuffer> createHandshake(Handshakedata handshakedata, Role ownrole,
      boolean withcontent) {
    return createHandshake(handshakedata, withcontent);
  }

  public List<ByteBuffer> createHandshake(Handshakedata handshakedata, boolean withcontent) {
    StringBuilder bui = new StringBuilder(100);
    if (handshakedata instanceof ClientHandshake) {
      bui.append("GET ").append(((ClientHandshake) handshakedata).getResourceDescriptor())
          .append(" HTTP/1.1");
    } else if (handshakedata instanceof ServerHandshake) {
      bui.append("HTTP/1.1 101 ").append(((ServerHandshake) handshakedata).getHttpStatusMessage());
    } else {
      throw new IllegalArgumentException("unknown role");
    }
    bui.append("\r\n");
    Iterator<String> it = handshakedata.iterateHttpFields();
    while (it.hasNext()) {
      String fieldname = it.next();
      String fieldvalue = handshakedata.getFieldValue(fieldname);
      bui.append(fieldname);
      bui.append(": ");
      bui.append(fieldvalue);
      bui.append("\r\n");
    }
    bui.append("\r\n");
    byte[] httpheader = Charsetfunctions.asciiBytes(bui.toString());

    byte[] content = withcontent ? handshakedata.getContent() : null;
    ByteBuffer bytebuffer = ByteBuffer
        .allocate((content == null ? 0 : content.length) + httpheader.length);
    bytebuffer.put(httpheader);

View on GitHub (pinned to afeacbf8c0)