{"record":{"id":"0b0aa88ed190f642","repo":"TooTallNate/Java-WebSocket","slug":"control-frame-can-t-have-fin-false-set","errorCode":null,"errorMessage":"Control frame can't have fin==false set","messagePattern":"Control frame can't have fin==false set","errorType":"exception","errorClass":"InvalidFrameException","httpStatus":null,"severity":"error","filePath":"src/main/java/org/java_websocket/framing/ControlFrame.java","lineNumber":49,"sourceCode":"\n/**\n * Abstract class to represent control frames\n */\npublic abstract class ControlFrame extends FramedataImpl1 {\n\n  /**\n   * Class to represent a control frame\n   *\n   * @param opcode the opcode to use\n   */\n  public ControlFrame(Opcode opcode) {\n    super(opcode);\n  }\n\n  @Override\n  public void isValid() throws InvalidDataException {\n    if (!isFin()) {\n      throw new InvalidFrameException(\"Control frame can't have fin==false set\");\n    }\n    if (isRSV1()) {\n      throw new InvalidFrameException(\"Control frame can't have rsv1==true set\");\n    }\n    if (isRSV2()) {\n      throw new InvalidFrameException(\"Control frame can't have rsv2==true set\");\n    }\n    if (isRSV3()) {\n      throw new InvalidFrameException(\"Control frame can't have rsv3==true set\");\n    }\n  }\n}\n","sourceCodeStart":31,"sourceCodeEnd":62,"githubUrl":"https://github.com/TooTallNate/Java-WebSocket/blob/afeacbf8c0f6f6a761c9d9daed8c813dd3b8ed7d/src/main/java/org/java_websocket/framing/ControlFrame.java#L31-L62","documentation":"Per RFC 6455, control frames (ping, pong, close) must never be fragmented: their FIN bit must be 1. ControlFrame.isValid rejects any control frame with FIN == 0 by throwing InvalidFrameException('Control frame can't have fin==false set').","triggerScenarios":"A ping/pong/close frame arrives (or is constructed) with the FIN bit set to 0. isValid() runs when the frame is processed or prepared for sending.","commonSituations":"Non-conformant clients/servers fragmenting control frames; hand-rolled frame builders forgetting to set FIN; fuzzed or malicious traffic from attackers probing the endpoint.","solutions":["Fix the peer implementation to always set FIN=1 on control frames.","If building control frames yourself, construct them via the library's ping()/sendPong()/close() APIs, which set FIN correctly.","Treat such traffic as a protocol violation and log/reject the peer.","Use a packet capture to confirm the raw frame's FIN bit before filing a bug."],"exampleFix":"// before: manual control frame without FIN\nFramedata ping = new FramedataImpl1(Opcode.PING);\nping.setFin(false); // invalid\n\n// after\nFramedata ping = new FramedataImpl1(Opcode.PING);\nping.setFin(true);","handlingStrategy":"validation","validationCode":"// control frames must be unfragmented\nif (isControlOpcode(frame.getOpcode()) && !frame.isFin()) {\n    throw new IllegalArgumentException(\"control frames must have FIN set\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    validateFrame(frame);\n} catch (InvalidFrameException e) {\n    logger.warn(\"protocol violation from peer: {}\", e.getMessage());\n    webSocket.close(1002, \"protocol error\");\n}","preventionTips":["Use the library's ping()/sendPong()/close() helpers instead of raw frames","Reject fragmented control frames as a protocol violation","Fuzz-test your endpoint for malformed frame headers"],"tags":["websocket","control-frame","fragmentation","rfc6455","frame-validation"],"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"}