actix/actix-web · error · ProtocolError
Unknown continuation fragment: {}
Error message
Unknown continuation fragment: {} What it means
This is `ws::ProtocolError::ContinuationFragment(OpCode)` from actix-http's WebSocket handling. A fragmented message must consist of a first frame (text/binary) followed only by continuation frames (opcode 0x0). This error is raised when a continuation frame arrives when no fragmented message is in progress, i.e. the fragment sequence state machine is out of sync.
Source
Thrown at actix-http/src/ws/mod.rs:78
/// Bad opcode.
#[display("Bad opcode")]
BadOpCode,
/// A payload reached size limit.
#[display("Payload reached size limit")]
Overflow,
/// Continuation has not started.
#[display("Continuation has not started")]
ContinuationNotStarted,
/// Received new continuation but it is already started.
#[display("Received new continuation but it has already started")]
ContinuationStarted,
/// Unknown continuation fragment.
#[display("Unknown continuation fragment: {}", _0)]
ContinuationFragment(#[error(not(source))] OpCode),
/// I/O error.
#[display("I/O error: {}", _0)]
Io(io::Error),
}
/// WebSocket handshake errors
#[derive(Debug, Clone, Copy, PartialEq, Eq, Display, Error)]
pub enum HandshakeError {
/// Only get method is allowed.
#[display("method not allowed")]
GetMethodRequired,
/// Upgrade header if not set to WebSocket.
#[display("WebSocket upgrade is expected")]
NoWebsocketUpgrade,
/// Connection header is not set to upgrade.View on GitHub (pinned to c215607f4b)
Solutions
- Fix the sending side so every fragmented message starts with an initial text/binary frame (FIN=0) before any continuation frames.
- Ensure only the last fragment has FIN=1 and that no extra continuation frames are sent after it.
- Check for intermediaries (proxies/load balancers) that could reorder or duplicate WebSocket frames and bypass or replace them.
- On error, reset the per-connection message state and close with CloseCode::Protocol; do not attempt to salvage the partial message.
Example fix
// before: sender starts fragments with opcode 0x0 send_frame(Frame::continuation(payload).fin(false)); // after: first fragment must carry the message type send_frame(Frame::text(payload).fin(false)); send_frame(Frame::continuation(rest).fin(true));
Defensive patterns
Strategy: try-catch
Validate before calling
// sender-side check before emitting a continuation frame
if (!fragmentationActive) throw new Error("continuation frame without an open fragmented message"); Type guard
struct FragmentState { in_progress: bool }
fn can_send_continuation(state: &FragmentState) -> bool {
state.in_progress
} Try / catch
match result {
Err(ProtocolError::ContinuationFragment(op)) => {
log::warn!("unexpected continuation fragment (op {:?}); resetting message state", op);
reset_assembler();
close_with(CloseCode::Protocol);
}
other => handle(other),
} Prevention
- Always start a fragmented message with a text/binary frame (FIN=0), never a continuation frame
- Set FIN=1 exactly once, on the final fragment
- Reset fragment state on reconnect; never resume mid-message after a dropped connection
- Test fragmented sends through any proxies to ensure frame order is preserved
When it happens
Trigger: The ws message assembler receives a continuation frame (opcode 0x0) while `continuation` state is None/finished — e.g. a lone continuation frame or a continuation after the FIN frame already closed the message.
Common situations: A peer that emits continuation frames without a preceding fragmented text/binary frame, double-sending the final fragment, a proxy reordering/dropping frames, or resuming a session mid-message after reconnecting.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- unknown continuation fragment: {}
- invalid opcode ({})
- invalid control frame length ({})
- Invalid opcode ({})
- Invalid control frame length ({})
AI-assisted analysis of actix/actix-web@c215607f4b (2026-09-09).
Data as JSON: /api/errors/30027b0d1c1dd7e6.
Report an issue: GitHub.