{"record":{"id":"ef57958d653368a7","repo":"actix/actix-web","slug":"invalid-control-frame-length","errorCode":null,"errorMessage":"invalid control frame length ({})","messagePattern":"invalid control frame length \\((.+?)\\)","errorType":"exception","errorClass":"ProtocolError","httpStatus":null,"severity":"error","filePath":"actix-http/src/ws/mod.rs","lineNumber":43,"sourceCode":"\n/// WebSocket protocol errors.\n#[derive(Debug, Display, Error, From)]\npub enum ProtocolError {\n    /// Received an unmasked frame from client.\n    #[display(\"received an unmasked frame from client\")]\n    UnmaskedFrame,\n\n    /// Received a masked frame from server.\n    #[display(\"received a masked frame from server\")]\n    MaskedFrame,\n\n    /// Encountered invalid opcode.\n    #[display(\"invalid opcode ({})\", _0)]\n    InvalidOpcode(#[error(not(source))] u8),\n\n    /// Invalid control frame length\n    #[display(\"invalid control frame length ({})\", _0)]\n    InvalidLength(#[error(not(source))] usize),\n\n    /// Bad opcode.\n    #[display(\"bad opcode\")]\n    BadOpCode,\n\n    /// A payload reached size limit.\n    #[display(\"payload reached size limit\")]\n    Overflow,\n\n    /// Continuation has not started.\n    #[display(\"continuation has not started\")]\n    ContinuationNotStarted,\n\n    /// Received new continuation but it is already started.\n    #[display(\"received new continuation but it has already started\")]\n    ContinuationStarted,\n\n    /// Unknown continuation fragment.","sourceCodeStart":25,"sourceCodeEnd":61,"githubUrl":"https://github.com/actix/actix-web/blob/4d435abc281842f3cbee165b6cde739e001d3a25/actix-http/src/ws/mod.rs#L25-L61","documentation":"ProtocolError::InvalidLength(usize) is raised in frame.rs:136 when a Ping or Pong control frame carries a payload longer than 125 bytes. RFC 6455 §5.5 mandates that all control frames have a payload length <= 125 and must set the FIN bit, so a larger Ping/Pong is a protocol violation. The length is read from the frame header in parse_metadata and checked after the payload is fully received.","triggerScenarios":"A peer sends a Ping or Pong frame whose declared payload length exceeds 125 bytes (e.g. a 200-byte ping). Close frames over 125 are not errored - they are morphed to an empty close (frame.rs:138) - but Ping/Pong are.","commonSituations":"A client library that incorrectly fragments or oversizes keep-alive Ping payloads; stress tests sending large pings; a faulty intermediary that re-encodes control frames.","solutions":["Keep Ping/Pong payloads at or below 125 bytes; use Text/Binary frames for larger data.","If you are the sender, use the standard Message::Ping which the Codec frames correctly.","Close the connection on this error (the actix WS dispatcher does so automatically)."],"exampleFix":"// before: oversized ping payload\nlet big = vec![0u8; 200];\nmsg = Message::Ping(Bytes::from(big));\n\n// after: payload <= 125 bytes\nlet small = vec![0u8; 64];\nmsg = Message::Ping(Bytes::from(small));","handlingStrategy":"validation","validationCode":"// Cap ping/pong payloads before sending\nfn safe_ping(data: Vec<u8>) -> Message {\n    let d = if data.len() > 125 { data[..125].to_vec() } else { data };\n    Message::Ping(Bytes::from(d))\n}","typeGuard":null,"tryCatchPattern":"match parse_result {\n    Err(ProtocolError::InvalidLength(n)) => {\n        log::warn!(\"control frame too long: {n}\");\n        close_with(CloseCode::Protocol);\n    }\n    _ => { /* ... */ }\n}","preventionTips":["Keep Ping/Pong payloads <= 125 bytes.","Never fragment control frames.","Use the standard Message::Ping/Pong constructors."],"tags":["websocket","protocol","actix-http","control-frame"],"backgroundTag":null,"analyzedSha":"4d435abc281842f3cbee165b6cde739e001d3a25","analyzedAt":"2026-08-09T01:01:40.926Z","contentChangedAt":"2026-08-09T01:01:40.926Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}