actix/actix-web · error · io::Error
Invalid chunk size LF
Error message
Invalid chunk size LF
What it means
io::Error(InvalidInput, "Invalid chunk size LF") (chunked.rs:116-119) is returned by read_size_lf when the byte following the chunk size (and optional extension) is not a lone LF after the expected CR. The state machine reaches SizeLf only after consuming a CR; a byte other than '\n' here breaks the required CRLF terminator.
Source
Thrown at actix-http/src/h1/chunked.rs:116
))),
}
}
fn read_extension(rdr: &mut BytesMut) -> Poll<Result<ChunkedState, io::Error>> {
match byte!(rdr) {
b'\r' => Poll::Ready(Ok(ChunkedState::SizeLf)),
// strictly 0x20 (space) should be disallowed but we don't parse quoted strings here
0x00..=0x08 | 0x0a..=0x1f | 0x7f => Poll::Ready(Err(io::Error::new(
io::ErrorKind::InvalidInput,
"Invalid character in chunk extension",
))),
_ => Poll::Ready(Ok(ChunkedState::Extension)), // no supported extensions
}
}
fn read_size_lf(rdr: &mut BytesMut, size: u64) -> Poll<Result<ChunkedState, io::Error>> {
match byte!(rdr) {
b'\n' if size > 0 => Poll::Ready(Ok(ChunkedState::Body)),
b'\n' if size == 0 => Poll::Ready(Ok(ChunkedState::EndCr)),
_ => Poll::Ready(Err(io::Error::new(
io::ErrorKind::InvalidInput,
"Invalid chunk size LF",
))),
}
}
fn read_body(
rdr: &mut BytesMut,
rem: &mut u64,
buf: &mut Option<Bytes>,
) -> Poll<Result<ChunkedState, io::Error>> {
trace!("Chunked read, remaining={:?}", rem);
let len = rdr.len() as u64;
if len == 0 {
Poll::Ready(Ok(ChunkedState::Body))
} else {
let slice;View on GitHub (pinned to 937960ca67)
Solutions
- Ensure every size line ends with a strict CRLF (0x0D 0x0A).
- Use Content-Length when the body length is known.
- Capture the wire bytes to confirm the terminator is missing.
Example fix
// before b"4\rX\ndata\r\n0\r\n\r\n" // after b"4\r\ndata\r\n0\r\n\r\n"
Defensive patterns
Strategy: try-catch
Try / catch
// Handle the malformed CRLF as a 400 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
- Always terminate chunk size lines with a strict CRLF (0x0D 0x0A).
- Use Content-Length when the body size is known.
- Verify proxies are not rewriting line endings.
When it happens
Trigger: A chunk size line uses a bare CR without LF, or inserts a character between CR and LF, e.g. '4\rX\n'. read_size emits SizeLf on the CR and read_size_lf sees 'X'.
Common situations: A non-conformant encoder using lone CR or inserting bytes inside the line terminator; line-ending corruption by a proxy.
Related errors
- Invalid chunk size line: Invalid Size
- Invalid chunk size linear white space
- Invalid chunk body CR
- Invalid chunk body LF
- Invalid chunk end CR
AI-assisted analysis of actix/actix-web@937960ca67 (2026-08-06).
Data as JSON: /data/errors/b4f995461c9eedce.json.
Report an issue: GitHub.