{"record":{"id":"ad26e9dee705e567","repo":"actix/actix-web","slug":"unknown-continuation-fragment","errorCode":null,"errorMessage":"unknown continuation fragment: {}","messagePattern":"unknown continuation fragment: (.+?)","errorType":"exception","errorClass":"ProtocolError","httpStatus":null,"severity":"error","filePath":"actix-http/src/ws/mod.rs","lineNumber":63,"sourceCode":"    /// 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.\n    #[display(\"unknown continuation fragment: {}\", _0)]\n    ContinuationFragment(#[error(not(source))] OpCode),\n\n    /// I/O error.\n    #[display(\"I/O error: {}\", _0)]\n    Io(io::Error),\n}\n\n/// WebSocket handshake errors\n#[derive(Debug, Clone, Copy, PartialEq, Eq, Display, Error)]\npub enum HandshakeError {\n    /// Only get method is allowed.\n    #[display(\"method not allowed\")]\n    GetMethodRequired,\n\n    /// Upgrade header if not set to WebSocket.\n    #[display(\"WebSocket upgrade is expected\")]\n    NoWebsocketUpgrade,\n\n    /// Connection header is not set to upgrade.","sourceCodeStart":45,"sourceCodeEnd":81,"githubUrl":"https://github.com/actix/actix-web/blob/4d435abc281842f3cbee165b6cde739e001d3a25/actix-http/src/ws/mod.rs#L45-L81","documentation":"ProtocolError::ContinuationFragment(OpCode) is raised in codec.rs:259 when an unfinished (FIN bit = 0) frame arrives with an opcode other than Continue/Text/Binary. RFC 6455 forbids fragmenting control frames (Close/Ping/Pong), so a non-final Close/Ping/Pong is logged as an unknown continuation fragment and rejected. It is distinct from ContinuationNotStarted/ContinuationStarted which track the fragmentation state machine.","triggerScenarios":"A peer sends a Close, Ping, or Pong frame with the FIN bit cleared (an attempt to fragment a control frame). The codec's decode (codec.rs:257) hits the wildcard arm and returns this error.","commonSituations":"A non-conformant client that fragments ping/pong keep-alives; a custom WS implementation misunderstanding the fragmentation rules; stream corruption flipping the FIN bit.","solutions":["Ensure control frames (Close/Ping/Pong) are always sent with FIN=1 and unfragmented.","Use the actix Codec/Message API which never fragments control frames.","Treat the error as fatal and close the connection (handled by the dispatcher)."],"exampleFix":"// before: control frame with FIN=0 (fragmented) - invalid\n// after: always set FIN=1 on Ping/Pong/Close via the standard message API\nframe.send(Message::Ping(payload)); // Codec sets FIN correctly","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"match decode_result {\n    Err(actix_http::ws::ProtocolError::ContinuationFragment(op)) => {\n        log::error!(\"fragmented control frame {op}\");\n        // RFC violation; terminate the connection\n        return Err(CloseCode::Protocol.into());\n    }\n    _ => { /* ... */ }\n}","preventionTips":["Always set FIN=1 on Close/Ping/Pong.","Use the actix Codec which never fragments control frames.","Treat this error as a connection-ending protocol violation."],"tags":["websocket","protocol","actix-http","fragmentation"],"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"}