actix/actix-web · error · ProtocolError
invalid control frame length
Error message
invalid control frame length ({}) What it means
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.
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).
Example fix
// before: oversized ping payload let big = vec![0u8; 200]; msg = Message::Ping(Bytes::from(big)); // after: payload <= 125 bytes let small = vec![0u8; 64]; msg = Message::Ping(Bytes::from(small));
Defensive patterns
Strategy: validation
Validate before calling
// Cap ping/pong payloads before sending
fn safe_ping(data: Vec<u8>) -> Message {
let d = if data.len() > 125 { data[..125].to_vec() } else { data };
Message::Ping(Bytes::from(d))
} Try / catch
match parse_result {
Err(ProtocolError::InvalidLength(n)) => {
log::warn!("control frame too long: {n}");
close_with(CloseCode::Protocol);
}
_ => { /* ... */ }
} Prevention
- Keep Ping/Pong payloads <= 125 bytes.
- Never fragment control frames.
- Use the standard Message::Ping/Pong constructors.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- invalid opcode ( )
- Invalid opcode ( )
- unknown continuation fragment
- Invalid chunk body CR
- Invalid chunk body LF
AI-assisted analysis of actix/actix-web@4d435abc28 (2026-08-09).
Data as JSON: /api/errors/ef57958d653368a7.
Report an issue: GitHub.
Appendix: source
Thrown at actix-http/src/ws/mod.rs:43
/// WebSocket protocol errors.
#[derive(Debug, Display, Error, From)]
pub enum ProtocolError {
/// Received an unmasked frame from client.
#[display("received an unmasked frame from client")]
UnmaskedFrame,
/// Received a masked frame from server.
#[display("received a masked frame from server")]
MaskedFrame,
/// Encountered invalid opcode.
#[display("invalid opcode ({})", _0)]
InvalidOpcode(#[error(not(source))] u8),
/// Invalid control frame length
#[display("invalid control frame length ({})", _0)]
InvalidLength(#[error(not(source))] usize),
/// 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.View on GitHub (pinned to 4d435abc28)