actix/actix-web · error · io::Error
Invalid chunk end CR
Error message
Invalid chunk end CR
What it means
Raised in read_end_cr (chunked.rs:172) when the byte following the terminating zero-size chunk's CRLF is not CR. A zero-length chunk ("0\r\n") signals the end of the chunked body; it must itself be followed by CRLF (the trailer block terminator). This state expects that leading CR.
Solutions
- Always send the terminating sequence "0\r\n\r\n" (last-chunk + empty trailer line).
- If sending trailers, ensure each trailer line ends with CRLF and the block is terminated by a final CRLF.
- Use a standard HTTP client to avoid hand-rolling the terminator.
Example fix
// before "0\r\n" // missing final CRLF // after "0\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(), // missing CR after last chunk
_ => { /* ... */ }
} Prevention
- Always terminate chunked bodies with "0\r\n\r\n".
- Include a final empty trailer line.
- Use a standards-compliant client.
When it happens
Trigger: After the final "0\r\n", the next byte is not CR - e.g. the stream omits the trailing CRLF or sends data where the trailer-terminating CRLF should be. read_size_lf routes a size==0 chunk to EndCr expecting '\r'.
Common situations: Client omitting the final CRLF after the last-chunk; truncated upload; proxy that drops the trailer terminator; malformed trailer section.
Related errors
- Invalid chunk body CR
- Invalid chunk body LF
- Invalid chunk end LF
- Invalid chunk size LF
- Invalid chunk size line: Invalid Size
AI-assisted analysis of actix/actix-web@4d435abc28 (2026-08-09).
Data as JSON: /api/errors/ec4ac6a50c92c701.
Report an issue: GitHub.
Appendix: source
Thrown at actix-http/src/h1/chunked.rs:172
_ => 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(
io::ErrorKind::InvalidInput,
"Invalid chunk end LF",
))),
}
}
}
#[cfg(test)]
mod tests {View on GitHub (pinned to 4d435abc28)