tokio-rs/tokio · error · LengthDelimitedCodecError

frame size too big

Error message

frame size too big

What it means

Runtime error from `LengthDelimitedCodec::decode_head` (length_delimited.rs:527). The length value read from the wire's length field exceeds the configured `max_frame_len`; it returns `LengthDelimitedCodecError` as `io::ErrorKind::InvalidData`. This guard bounds memory use against a bogus/hostile length header.

Source

Thrown at tokio-util/src/codec/length_delimited.rs:527

            // Not enough data
            return Ok(None);
        }

        let n = {
            let mut src = Cursor::new(&mut *src);

            // Skip the required bytes
            src.advance(self.builder.length_field_offset);

            // match endianness
            let n = if self.builder.length_field_is_big_endian {
                src.get_uint(field_len)
            } else {
                src.get_uint_le(field_len)
            };

            if n > self.builder.max_frame_len as u64 {
                return Err(io::Error::new(
                    io::ErrorKind::InvalidData,
                    LengthDelimitedCodecError { _priv: () },
                ));
            }

            // The check above ensures there is no overflow
            let n = n as usize;

            // Adjust `n` with bounds checking
            let n = if self.builder.length_adjustment < 0 {
                n.checked_sub(-self.builder.length_adjustment as usize)
            } else {
                n.checked_add(self.builder.length_adjustment as usize)
            };

            // Error handling
            match n {
                Some(n) => n,

View on GitHub (pinned to 625954f365)

Solutions

  1. If frames are legitimately large, raise the cap: `LengthDelimitedCodec::builder().max_frame_length(N)`.
  2. Verify `length_field_len`, `length_field_offset`, and `length_field_is_big_endian` match the peer's wire format.
  3. Treat the error as a protocol violation and close the connection when reading from an untrusted peer.
  4. Always set a sane `max_frame_length` to bound buffer growth.

Example fix

// before: default 8MB cap rejects a 16MB frame
let codec = LengthDelimitedCodec::new();

// after: raise the cap to match the protocol
let codec = LengthDelimitedCodec::builder()
    .max_frame_length(16 * 1024 * 1024)
    .new_codec();
Defensive patterns

Strategy: validation

Validate before calling

// Validate builder settings before use
let max = codec.max_frame_length();
debug_assert!(max >= protocol_max_frame, "codec max smaller than protocol allows");
assert!(length_field_len <= 8 && length_field_offset + length_field_len <= header_len);

Type guard

fn is_frame_too_big(e: &io::Error) -> bool {
    e.kind() == io::ErrorKind::InvalidData && e.get_ref().map(|x| x.is::<LengthDelimitedCodecError>()).unwrap_or(false)
}

Try / catch

match framed.next().await {
    Some(Err(e)) if is_frame_too_big(&e) => { close_peer().await; continue; }
    Some(Err(e)) => return Err(e.into()),
    Some(Ok(f)) => handle(f),
    None => break,
}

Prevention

When it happens

Trigger: The decoded length-field value is larger than `max_frame_length()`. Causes: peer sends a frame larger than the local cap; corrupt bytes; wrong `length_field_len`/`length_field_offset`/endianness so garbage is read as the length; adversarial input.

Common situations: Peer and local disagree on max frame size; builder misconfiguration (wrong endianness, wrong field width, wrong offset) making a small frame look huge; forgot to raise `max_frame_length` for a protocol with large frames; malicious/untrusted peer.

Related errors


AI-assisted analysis of tokio-rs/tokio@625954f365 (2026-08-11). Data as JSON: /api/errors/c6d1d782196e6cfc. Report an issue: GitHub.