actix/actix-web · error · io::Error

Invalid chunk body LF

Error message

Invalid chunk body LF

What it means

io::Error(InvalidInput, "Invalid chunk body LF") (chunked.rs:163-166) is returned by read_body_lf when the byte after the chunk-body CR is not an LF. The parser reached BodyLf by consuming the CR terminator; anything other than '\n' breaks the CRLF that must follow each chunk body.

Source

Thrown at actix-http/src/h1/chunked.rs:163

            } else {
                Poll::Ready(Ok(ChunkedState::BodyCr))
            }
        }
    }

    fn read_body_cr(rdr: &mut BytesMut) -> Poll<Result<ChunkedState, io::Error>> {
        match byte!(rdr) {
            b'\r' => Poll::Ready(Ok(ChunkedState::BodyLf)),
            _ => Poll::Ready(Err(io::Error::new(
                io::ErrorKind::InvalidInput,
                "Invalid chunk body CR",
            ))),
        }
    }
    fn read_body_lf(rdr: &mut BytesMut) -> Poll<Result<ChunkedState, io::Error>> {
        match byte!(rdr) {
            b'\n' => Poll::Ready(Ok(ChunkedState::Size)),
            _ => Poll::Ready(Err(io::Error::new(
                io::ErrorKind::InvalidInput,
                "Invalid chunk body LF",
            ))),
        }
    }
    fn read_end_cr(rdr: &mut BytesMut) -> Poll<Result<ChunkedState, io::Error>> {
        match byte!(rdr) {
            b'\r' => Poll::Ready(Ok(ChunkedState::EndLf)),
            _ => Poll::Ready(Err(io::Error::new(
                io::ErrorKind::InvalidInput,
                "Invalid chunk end CR",
            ))),
        }
    }
    fn read_end_lf(rdr: &mut BytesMut) -> Poll<Result<ChunkedState, io::Error>> {
        match byte!(rdr) {
            b'\n' => Poll::Ready(Ok(ChunkedState::End)),
            _ => Poll::Ready(Err(io::Error::new(

View on GitHub (pinned to 937960ca67)

Solutions

  1. Ensure each chunk body ends with a strict CRLF.
  2. Capture the raw stream around the chunk boundary.
  3. Prefer Content-Length for fixed-size bodies.
Defensive patterns

Strategy: try-catch

Try / catch

// Lone-CR terminator -> treat as bad request.
use actix_http::error::PayloadError;
if matches!(payload.next().await, Some(Err(PayloadError::Io(e))) if e.kind() == io::ErrorKind::InvalidInput) {
    return HttpResponse::BadRequest().finish();
}

Prevention

When it happens

Trigger: A chunk body is terminated with CR plus a non-LF byte, e.g. the encoder wrote '\r.' instead of '\r\n'. read_body_cr accepted the CR and advanced to BodyLf, which then sees the stray byte.

Common situations: Lone-CR terminators from a broken encoder, or proxy corruption of the line ending.

Related errors


AI-assisted analysis of actix/actix-web@937960ca67 (2026-08-06). Data as JSON: /data/errors/86bc4326863da986.json. Report an issue: GitHub.