hyperium/hyper · error · std::io::Error
Invalid chunk body LF
Error message
Invalid chunk body LF
What it means
Thrown in read_body_lf (src/proto/h1/decode.rs:523) after the CR following a chunk's data: the next byte must be '\n' to complete the CRLF. Any other byte yields io::ErrorKind::InvalidInput — the chunk trailer CRLF is broken (CR present, LF missing).
Source
Thrown at src/proto/h1/decode.rs:523
fn read_body_cr<R: MemRead>(
cx: &mut Context<'_>,
rdr: &mut R,
) -> Poll<Result<ChunkedState, io::Error>> {
match byte!(rdr, cx) {
b'\r' => Poll::Ready(Ok(ChunkedState::BodyLf)),
_ => Poll::Ready(Err(io::Error::new(
io::ErrorKind::InvalidInput,
"Invalid chunk body CR",
))),
}
}
fn read_body_lf<R: MemRead>(
cx: &mut Context<'_>,
rdr: &mut R,
) -> Poll<Result<ChunkedState, io::Error>> {
match byte!(rdr, cx) {
b'\n' => Poll::Ready(Ok(ChunkedState::Start)),
_ => Poll::Ready(Err(io::Error::new(
io::ErrorKind::InvalidInput,
"Invalid chunk body LF",
))),
}
}
fn read_trailer<R: MemRead>(
cx: &mut Context<'_>,
rdr: &mut R,
trailers_buf: &mut Option<BytesMut>,
h1_max_header_size: usize,
) -> Poll<Result<ChunkedState, io::Error>> {
trace!("read_trailer");
let byte = byte!(rdr, cx);
put_u8!(
trailers_buf.as_mut().expect("trailers_buf is None"),
byte,View on GitHub (pinned to 084473f728)
Solutions
- Ensure every chunk is followed by a full CRLF (\r\n), not a lone CR.
- Disable any body newline normalization/transcoding in upstream proxies.
- Write framing with a single literal "\r\n" buffer to avoid splitting CR and LF writes.
Example fix
// before: CR and LF written through separate paths that drop LF
write!(w, "{:x}\r\n", len).await?;
w.write_all(&data).await?;
w.write_all(b"\r").await?; // LF lost downstream -> error 28
// after: emit the full terminator atomically
w.write_all(b"\r\n").await?; Defensive patterns
Strategy: try-catch
Try / catch
Some(Err(e)) => {
let kind = e.source()
.and_then(|s| s.downcast_ref::<std::io::Error>())
.map(|io| io.kind());
if matches!(kind, Some(std::io::ErrorKind::InvalidInput)) {
tracing::warn!(error=%e, "chunk data terminator CR not followed by LF");
break;
}
return Err(e.into());
} Prevention
- Write each chunk's trailing CRLF as one literal b"\r\n" write.
- Disable any proxy/middleware that normalizes CRLF→CR in the body.
- Unit-test your chunker against hyper's Decoder::chunked(None,None) decoder.
When it happens
Trigger: A chunk like "10\r\n1234567890abcdef\rX" where the byte after the data-terminating CR is 'X' instead of LF; a transport or middleware that drops the LF after the data.
Common situations: A newline-normalizing proxy that converts CRLF→CR in the body; a buggy sender that writes only "\r" after each chunk; byte-level corruption on the link.
Related errors
- Invalid chunk size line: missing size digit
- Invalid chunk size line: Invalid Size
- Invalid chunk size linear white space
- Invalid chunk size LF
- Invalid chunk body CR
AI-assisted analysis of hyperium/hyper@084473f728 (2026-08-06).
Data as JSON: /data/errors/6162ddc841560d21.json.
Report an issue: GitHub.