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
- Implement your handshake object as ClientHandshake (client requests) or ServerHandshake (server responses)
- Use the library's own HandshakeImpl1Client/HandshakeImpl1Server classes instead of custom implementations
- 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
- Use HandshakeImpl1Client/HandshakeImpl1Server, not custom implementations
- In tests, build handshakes through the library types
- Keep the role marker interfaces on any custom handshake subclass
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
- buffer size < 0
- Invalid status code received
- Only Opcode.BINARY or Opcode.TEXT are allowed
- missing Sec-WebSocket-Key
- http resource descriptor must not be null
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)