TooTallNate/Java-WebSocket · error · InvalidFrameException
bad rsv RSV1: RSV2: RSV3
Error message
bad rsv RSV1: {rsv1} RSV2: {rsv2} RSV3: {rsv3} What it means
DefaultExtension.isFrameValid is the base validation for extensions with no negotiated RSV usage: it rejects any frame with RSV1, RSV2, or RSV3 set, throwing InvalidFrameException (close code 1002, PROTOCOL_ERROR). This is the generic 'RSV bits set but no extension negotiated to use them' violation required by RFC 6455.
Solutions
- Enable the compression extension on the server: new Draft_6455(Collections.singletonList(new PerMessageDeflateExtension()))
- Ensure client and server drafts negotiate the same extensions (check Sec-WebSocket-Extensions in the handshake)
- If no compression is intended, fix the peer to send frames with all RSV bits cleared
- Note this exact call also appears in tests (testIsFrameValid); when writing extensions, override isFrameValid to allow the RSV bits your extension owns
Example fix
// before: server draft without extensions, client sends RSV1 frames WebSocketServer wss = new WebSocketServer(addr, Collections.singletonList(new Draft_6455())); // after Draft_6455 draft = new Draft_6455(Collections.singletonList(new PerMessageDeflateExtension())); WebSocketServer wss = new WebSocketServer(addr, Collections.singletonList(draft));
Defensive patterns
Strategy: try-catch
Validate before calling
// verify extension negotiation before relying on RSV1 compression
String ext = responseHeader("Sec-WebSocket-Extensions");
boolean deflateNegotiated = ext != null && ext.contains("permessage-deflate");
if (!deflateNegotiated) { compressFrames = false; } Try / catch
@Override public void onClose(int code, String reason, boolean remote) {
if (code == 1002 && reason.startsWith("bad rsv")) {
// peer sent RSV bits but no extension was negotiated
reconnectWithoutCompression();
}
} Prevention
- Configure matching extensions on both client and server drafts
- Check Sec-WebSocket-Extensions in the handshake to confirm negotiation
- If compression is not needed, ensure clients clear all RSV bits
- When writing a custom extension, override isFrameValid to permit the RSV bits you own
When it happens
Trigger: A peer sets any RSV bit (e.g. RSV1=1 implying permessage-deflate) on a connection where only DefaultExtension is negotiated — i.e. the client offered the extension but the server declined it, or the client sets RSV bits without offering the extension at all.
Common situations: Client always marks frames compressed but the server has no compression extension in its draft (new Draft_6455() without extensions); mismatched drafts between client and server after a library upgrade; proxies stripping the Sec-WebSocket-Extensions header so negotiation silently fails.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
AI-assisted analysis of TooTallNate/Java-WebSocket@afeacbf8c0 (2026-09-09).
Data as JSON: /api/errors/4d6470a9dc0ed51a.
Report an issue: GitHub.
Appendix: source
Thrown at src/main/java/org/java_websocket/extensions/DefaultExtension.java:64
@Override
public void encodeFrame(Framedata inputFrame) {
//Nothing to do here
}
@Override
public boolean acceptProvidedExtensionAsServer(String inputExtension) {
return true;
}
@Override
public boolean acceptProvidedExtensionAsClient(String inputExtension) {
return true;
}
@Override
public void isFrameValid(Framedata inputFrame) throws InvalidDataException {
if (inputFrame.isRSV1() || inputFrame.isRSV2() || inputFrame.isRSV3()) {
throw new InvalidFrameException(
"bad rsv RSV1: " + inputFrame.isRSV1() + " RSV2: " + inputFrame.isRSV2() + " RSV3: "
+ inputFrame.isRSV3());
}
}
@Override
public String getProvidedExtensionAsClient() {
return "";
}
@Override
public String getProvidedExtensionAsServer() {
return "";
}
@Override
public IExtension copyInstance() {
return new DefaultExtension();View on GitHub (pinned to afeacbf8c0)