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

Invalid chunk size line: Invalid Size

Error message

Invalid chunk size line: Invalid Size

What it means

io::Error(InvalidInput, "Invalid chunk size line: Invalid Size") (chunked.rs:65-68) is returned by ChunkedState::read_size when the first byte of a chunk size field is not a hex digit, whitespace, ';', or CR. It aborts decoding of a Transfer-Encoding: chunked HTTP/1.1 body whose framing is malformed, surfacing as PayloadError::Io to the request/response reader.

Source

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

            BodyLf => ChunkedState::read_body_lf(body),
            EndCr => ChunkedState::read_end_cr(body),
            EndLf => ChunkedState::read_end_lf(body),
            End => Poll::Ready(Ok(ChunkedState::End)),
        }
    }

    fn read_size(rdr: &mut BytesMut, size: &mut u64) -> Poll<Result<ChunkedState, io::Error>> {
        let radix = 16;

        let rem = match byte!(rdr) {
            b @ b'0'..=b'9' => b - b'0',
            b @ b'a'..=b'f' => b + 10 - b'a',
            b @ b'A'..=b'F' => b + 10 - b'A',
            b'\t' | b' ' => return Poll::Ready(Ok(ChunkedState::SizeLws)),
            b';' => return Poll::Ready(Ok(ChunkedState::Extension)),
            b'\r' => return Poll::Ready(Ok(ChunkedState::SizeLf)),
            _ => {
                return Poll::Ready(Err(io::Error::new(
                    io::ErrorKind::InvalidInput,
                    "Invalid chunk size line: Invalid Size",
                )));
            }
        };

        match size.checked_mul(radix) {
            Some(n) => {
                *size = n;
                *size += rem as u64;

                Poll::Ready(Ok(ChunkedState::Size))
            }
            None => {
                debug!("chunk size would overflow u64");
                Poll::Ready(Err(io::Error::new(
                    io::ErrorKind::InvalidInput,
                    "Invalid chunk size line: Size is too big",

View on GitHub (pinned to 937960ca67)

Solutions

  1. Fix the peer to emit valid hex chunk sizes terminated by CRLF.
  2. If you do not need chunked encoding, send a Content-Length instead.
  3. Capture the raw bytes on the wire to locate the malformed line.

Example fix

// before: non-hex chunk size
b"G\r\ndata\r\n0\r\n\r\n"

// after: valid hex size
b"4\r\ndata\r\n0\r\n\r\n"
Defensive patterns

Strategy: try-catch

Try / catch

// PayloadError surfaces when reading the request/response body.
use actix_http::error::PayloadError;
match body.next().await {
    Some(Err(PayloadError::Io(e))) if e.kind() == io::ErrorKind::InvalidInput => {
        // malformed chunked framing; reject the request as 400
        return HttpResponse::BadRequest().finish();
    }
    Some(other) => { /* ... */ }
    None => { /* done */ }
}

Prevention

When it happens

Trigger: A chunked HTTP/1.1 request or response begins a chunk-size line with an illegal character, e.g. 'G\r\n' instead of a hex size. The state machine in chunked.rs:54-69 hits the default arm.

Common situations: A buggy client/server hand-rolling chunked encoding, a proxy corrupting the stream, or a fuzzer probing the parser. Browsers and curl never produce this.

Related errors


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