TooTallNate/Java-WebSocket · error · InvalidFrameException
Continuous frame cannot have RSV1, RSV2 or RSV3 set
Error message
Continuous frame cannot have RSV1, RSV2 or RSV3 set
What it means
PerMessageDeflateExtension.isFrameValid enforces RFC 7692 fragmentation rules: RSV1 may only be set on the first fragment of a compressed message, and RSV2/RSV3 are never allowed. When a continuous (non-first) frame carries any RSV bit, the extension rejects it with this InvalidFrameException to prevent malformed compressed messages from entering the decompression path.
Solutions
- Fix the peer so it only sets RSV1 on the first frame of a compressed message and leaves RSV bits unset on continuation frames.
- Verify the negotiated extension is permessage-deflate on both sides; if you don't intend compression, exclude the extension from the negotiated extensions so RSV1 semantics don't apply.
- If you control frame construction, build continuation frames with rsv1/rsv2/rsv3 = false.
- Capture the raw frames (e.g. with a proxy or packet capture) to confirm which RSV bits the peer sets before blaming this library.
Example fix
// before: building continuation frames with compression flag re-applied Framedata cont = new FramedataImpl1(PartialMessageOpcode); cont.setRSV1(true); // invalid on continuation // after: RSV bits only on the first fragment Framedata cont = new FramedataImpl1(Opcode.CONTINUOUS); cont.setRSV1(false);
Defensive patterns
Strategy: validation
Validate before calling
// before accepting/creating a continuation frame
if (frame.getOpcode() == Opcode.CONTINUOUS && (frame.isRSV1() || frame.isRSV2() || frame.isRSV3())) {
throw new IllegalArgumentException("RSV bits must not be set on continuation frames");
} Prevention
- Set RSV1 only on the first frame of a compressed message
- Use the library's send APIs rather than hand-building frames
- Test fragmented+compressed message paths against conformant peers
When it happens
Trigger: A WebSocket message is fragmented and a continuation frame (opcode 0) arrives with RSV1, RSV2, or RSV3 set in its header. Happens when a peer incorrectly re-sets the permessage-deflate RSV1 bit on each fragment, or sends garbage control bits on continuation frames.
Common situations: Interoperating with a non-conformant WebSocket client/server that marks every fragment as compressed; hand-rolled WebSocket frame implementations; proxies or middleware that rewrite frame headers and accidentally preserve or set RSV bits on continuation frames.
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
- bad rsv RSV1: RSV2: RSV3
- 1008
- 1007
- Inflated fragment size exceeds limit of
- closecode must not be sent over the wire
AI-assisted analysis of TooTallNate/Java-WebSocket@afeacbf8c0 (2026-09-09).
Data as JSON: /api/errors/a66168adcb476bfe.
Report an issue: GitHub.
Appendix: source
Thrown at src/main/java/org/java_websocket/extensions/permessage_deflate/PerMessageDeflateExtension.java:192
*
* <p>IMPORTANT: This API must be called on the class instance used by the library, NOT on the
* instance which was handed to the library! To get this class instance, retrieve it from the
* library e.g. via ((Draft_6455) webSocketClient.getConnection().getDraft()).getExtension().
* Make sure to apply class instance checks, as the extension may not have been negotiated.
*
* @return the overall compression ratio of all incoming and outgoing payloads
*/
public double getCompressionRatio() {
double decompressed = decompressedBytes;
return decompressed > 0 ? compressedBytes / decompressed : 1;
}
@Override
public void isFrameValid(Framedata inputFrame) throws InvalidDataException {
// RFC 7692: RSV1 may only be set for the first fragment of a message
if (inputFrame instanceof ContinuousFrame
&& (inputFrame.isRSV1() || inputFrame.isRSV2() || inputFrame.isRSV3())) {
throw new InvalidFrameException("Continuous frame cannot have RSV1, RSV2 or RSV3 set");
}
super.isFrameValid(inputFrame);
}
@Override
public void decodeFrame(Framedata inputFrame) throws InvalidDataException {
// RFC 7692: PMCEs operate only on data messages.
if (!(inputFrame instanceof DataFrame)) {
return;
}
// decompression is only applicable if it was started on the first fragment
if (!isDecompressing && inputFrame instanceof ContinuousFrame) {
return;
}
// check the RFC 7692 compression marker RSV1 whether to start decompressing
if (inputFrame.isRSV1()) {View on GitHub (pinned to afeacbf8c0)