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

Invalid chunk body LF

Error message

Invalid chunk body LF

What it means

Raised in read_body_lf (chunked.rs:163) when, after the CR following a chunk body, the next byte is not '\n'. Together with read_body_cr it enforces the CRLF that must terminate each chunk; a missing LF means the framing is broken and the parser rejects the stream.

Solutions

  1. Terminate every chunk body with a full CRLF (\r\n) before the next chunk-size line.
  2. Use a compliant HTTP serializer library.
  3. Inspect proxy CRLF handling if errors appear only behind a reverse proxy.

Example fix

// before
"4\r\nabcd\r0\r\n\r\n"
// after
"4\r\nabcd\r\n0\r\n\r\n"
Defensive patterns

Strategy: try-catch

Try / catch

match payload.next().await {
    Some(Err(PayloadError::Io(e))) if e.kind() == io::ErrorKind::InvalidInput =>
        return HttpResponse::BadRequest().finish(), // chunk body LF missing
    _ => { /* ... */ }
}

Prevention

When it happens

Trigger: A chunk body is followed by CR then a non-LF byte (e.g. CR followed by more data or a digit of the next size with no LF). read_body_lf only accepts '\n', transitioning back to the Size state on success.

Common situations: Inconsistent line endings; corrupt stream; proxy stripping LF characters; client bug emitting only CR after chunk data.

Related errors


AI-assisted analysis of actix/actix-web@4d435abc28 (2026-08-09). Data as JSON: /api/errors/86bc4326863da986. Report an issue: GitHub.

Appendix: 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 4d435abc28)