{"record":{"id":"a66168adcb476bfe","repo":"TooTallNate/Java-WebSocket","slug":"continuous-frame-cannot-have-rsv1-rsv2-or-rsv3-se","errorCode":null,"errorMessage":"Continuous frame cannot have RSV1, RSV2 or RSV3 set","messagePattern":"Continuous frame cannot have RSV1, RSV2 or RSV3 set","errorType":"exception","errorClass":"InvalidFrameException","httpStatus":null,"severity":"error","filePath":"src/main/java/org/java_websocket/extensions/permessage_deflate/PerMessageDeflateExtension.java","lineNumber":192,"sourceCode":"   *\n   * <p>IMPORTANT: This API must be called on the class instance used by the library, NOT on the\n   * instance which was handed to the library! To get this class instance, retrieve it from the\n   * library e.g. via ((Draft_6455) webSocketClient.getConnection().getDraft()).getExtension().\n   * Make sure to apply class instance checks, as the extension may not have been negotiated.\n   *\n   * @return the overall compression ratio of all incoming and outgoing payloads\n   */\n  public double getCompressionRatio() {\n    double decompressed = decompressedBytes;\n    return decompressed > 0 ? compressedBytes / decompressed : 1;\n  }\n\n  @Override\n  public void isFrameValid(Framedata inputFrame) throws InvalidDataException {\n    // RFC 7692: RSV1 may only be set for the first fragment of a message\n    if (inputFrame instanceof ContinuousFrame\n        && (inputFrame.isRSV1() || inputFrame.isRSV2() || inputFrame.isRSV3())) {\n      throw new InvalidFrameException(\"Continuous frame cannot have RSV1, RSV2 or RSV3 set\");\n    }\n    super.isFrameValid(inputFrame);\n  }\n\n  @Override\n  public void decodeFrame(Framedata inputFrame) throws InvalidDataException {\n    // RFC 7692: PMCEs operate only on data messages.\n    if (!(inputFrame instanceof DataFrame)) {\n      return;\n    }\n\n    // decompression is only applicable if it was started on the first fragment\n    if (!isDecompressing && inputFrame instanceof ContinuousFrame) {\n      return;\n    }\n\n    // check the RFC 7692 compression marker RSV1 whether to start decompressing\n    if (inputFrame.isRSV1()) {","sourceCodeStart":174,"sourceCodeEnd":210,"githubUrl":"https://github.com/TooTallNate/Java-WebSocket/blob/afeacbf8c0f6f6a761c9d9daed8c813dd3b8ed7d/src/main/java/org/java_websocket/extensions/permessage_deflate/PerMessageDeflateExtension.java#L174-L210","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before: building continuation frames with compression flag re-applied\nFramedata cont = new FramedataImpl1(PartialMessageOpcode);\ncont.setRSV1(true); // invalid on continuation\n\n// after: RSV bits only on the first fragment\nFramedata cont = new FramedataImpl1(Opcode.CONTINUOUS);\ncont.setRSV1(false);","handlingStrategy":"validation","validationCode":"// before accepting/creating a continuation frame\nif (frame.getOpcode() == Opcode.CONTINUOUS && (frame.isRSV1() || frame.isRSV2() || frame.isRSV3())) {\n    throw new IllegalArgumentException(\"RSV bits must not be set on continuation frames\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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"],"tags":["websocket","rfc7692","permessage-deflate","frame-validation","compression"],"backgroundTag":"invalid-argument-value","analyzedSha":"afeacbf8c0f6f6a761c9d9daed8c813dd3b8ed7d","analyzedAt":"2026-09-09T14:39:47.546Z","contentChangedAt":"2026-09-09T14:39:47.546Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}