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

Invalid chunk end LF

Error message

Invalid chunk end LF

What it means

io::Error(InvalidInput, "Invalid chunk end LF") (chunked.rs:181-184) is returned by read_end_lf when, after the final CR of the chunked trailer, the next byte is not an LF. This is the last byte of the chunked message; anything other than '\n' means the trailer CRLF is broken.

Source

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

            _ => 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(
                io::ErrorKind::InvalidInput,
                "Invalid chunk end LF",
            ))),
        }
    }
}

#[cfg(test)]
mod tests {
    use actix_codec::Decoder as _;
    use bytes::{Bytes, BytesMut};
    use http::Method;

    use crate::{
        error::ParseError,
        h1::decoder::{MessageDecoder, PayloadItem},
        HttpMessage as _, Request,
    };

View on GitHub (pinned to 937960ca67)

Solutions

  1. Ensure the message terminates with '0\r\n\r\n'.
  2. Confirm the peer flushes the full trailer before closing the socket.
  3. Capture the final bytes of the stream to locate the corruption.
Defensive patterns

Strategy: try-catch

Try / catch

// Corrupt final LF -> incomplete/malformed body.
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: The chunked stream's final CRLF is corrupted, e.g. '0\r\n\rX' — read_end_cr consumed the CR and read_end_lf sees 'X' instead of '\n'.

Common situations: A truncated or corrupt trailer from a buggy encoder or proxy; connection closed mid-trailer.

Related errors


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