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
- If frames are legitimately large, raise the cap: `LengthDelimitedCodec::builder().max_frame_length(N)`.
- Verify `length_field_len`, `length_field_offset`, and `length_field_is_big_endian` match the peer's wire format.
- Treat the error as a protocol violation and close the connection when reading from an untrusted peer.
- 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
- Agree on and set `max_frame_length` identically on both peers.
- Triple-check `length_field_len`, `length_field_offset`, and endianness against the spec.
- Always bound `max_frame_length` when reading from untrusted peers.
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
- bytes remaining on stream
- failed to write frame to transport
- provided length would overflow after adjustment
- failed to write entire datagram to socket
- Unable to decode input as UTF8
AI-assisted analysis of tokio-rs/tokio@625954f365 (2026-08-11).
Data as JSON: /api/errors/c6d1d782196e6cfc.
Report an issue: GitHub.