{"record":{"id":"ec4ac6a50c92c701","repo":"actix/actix-web","slug":"invalid-chunk-end-cr","errorCode":null,"errorMessage":"Invalid chunk end CR","messagePattern":"Invalid chunk end CR","errorType":"exception","errorClass":"io::Error","httpStatus":null,"severity":"error","filePath":"actix-http/src/h1/chunked.rs","lineNumber":172,"sourceCode":"            _ => Poll::Ready(Err(io::Error::new(\n                io::ErrorKind::InvalidInput,\n                \"Invalid chunk body CR\",\n            ))),\n        }\n    }\n    fn read_body_lf(rdr: &mut BytesMut) -> Poll<Result<ChunkedState, io::Error>> {\n        match byte!(rdr) {\n            b'\\n' => Poll::Ready(Ok(ChunkedState::Size)),\n            _ => Poll::Ready(Err(io::Error::new(\n                io::ErrorKind::InvalidInput,\n                \"Invalid chunk body LF\",\n            ))),\n        }\n    }\n    fn read_end_cr(rdr: &mut BytesMut) -> Poll<Result<ChunkedState, io::Error>> {\n        match byte!(rdr) {\n            b'\\r' => Poll::Ready(Ok(ChunkedState::EndLf)),\n            _ => Poll::Ready(Err(io::Error::new(\n                io::ErrorKind::InvalidInput,\n                \"Invalid chunk end CR\",\n            ))),\n        }\n    }\n    fn read_end_lf(rdr: &mut BytesMut) -> Poll<Result<ChunkedState, io::Error>> {\n        match byte!(rdr) {\n            b'\\n' => Poll::Ready(Ok(ChunkedState::End)),\n            _ => Poll::Ready(Err(io::Error::new(\n                io::ErrorKind::InvalidInput,\n                \"Invalid chunk end LF\",\n            ))),\n        }\n    }\n}\n\n#[cfg(test)]\nmod tests {","sourceCodeStart":154,"sourceCodeEnd":190,"githubUrl":"https://github.com/actix/actix-web/blob/4d435abc281842f3cbee165b6cde739e001d3a25/actix-http/src/h1/chunked.rs#L154-L190","documentation":"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.","triggerScenarios":"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'.","commonSituations":"Client omitting the final CRLF after the last-chunk; truncated upload; proxy that drops the trailer terminator; malformed trailer section.","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."],"exampleFix":"// before\n\"0\\r\\n\"  // missing final CRLF\n// after\n\"0\\r\\n\\r\\n\"","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"match payload.next().await {\n    Some(Err(PayloadError::Io(e))) if e.kind() == io::ErrorKind::InvalidInput =>\n        return HttpResponse::BadRequest().finish(), // missing CR after last chunk\n    _ => { /* ... */ }\n}","preventionTips":["Always terminate chunked bodies with \"0\\r\\n\\r\\n\".","Include a final empty trailer line.","Use a standards-compliant client."],"tags":["http","chunked-encoding","actix-http","protocol"],"backgroundTag":null,"analyzedSha":"4d435abc281842f3cbee165b6cde739e001d3a25","analyzedAt":"2026-08-09T01:01:40.926Z","contentChangedAt":"2026-08-09T01:01:40.926Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}