hyperium/hyper · error · std::io::Error

invalid chunk size: overflow

Error message

invalid chunk size: overflow

What it means

Thrown in the HTTP/1 chunked decoder via the or_overflow! macro (src/proto/h1/decode.rs:268) as io::Error::new(InvalidData, "invalid chunk size: overflow"). It fires when the hex chunk-size being parsed would exceed u64 — i.e. the chunk-size field has so many hex digits it overflows. It is raised inside read_start/read_size (decode.rs:352-393) every time a digit shifts the accumulator with checked_mul/checked_add that returns None.

Source

Thrown at src/proto/h1/decode.rs:268

}

macro_rules! byte (
    ($rdr:ident, $cx:expr) => ({
        let buf = ready!($rdr.read_mem($cx, 1))?;
        if !buf.is_empty() {
            buf[0]
        } else {
            return Poll::Ready(Err(io::Error::new(io::ErrorKind::UnexpectedEof,
                                      "unexpected EOF during chunk size line")));
        }
    })
);

macro_rules! or_overflow {
    ($e:expr) => (
        match $e {
            Some(val) => val,
            None => return Poll::Ready(Err(io::Error::new(
                io::ErrorKind::InvalidData,
                "invalid chunk size: overflow",
            ))),
        }
    )
}

macro_rules! put_u8 {
    ($trailers_buf:expr, $byte:expr, $limit:expr) => {
        $trailers_buf.put_u8($byte);

        if $trailers_buf.len() >= $limit {
            return Poll::Ready(Err(io::Error::new(
                io::ErrorKind::InvalidData,
                "chunk trailers bytes over limit",
            )));
        }
    };

View on GitHub (pinned to 084473f728)

Solutions

  1. Treat it as a corrupt/malicious request — close the connection and do not process the body.
  2. If you control the producer, ensure chunk sizes are correct hex and far below u64::MAX (realistically bounded by your buffer/body limits).
  3. Add a request body-size limit (and a WAF/rate-limiter) so oversized/abusive chunked uploads are rejected earlier.

Example fix

// (consumer side) before: assume any body is well-formed
let bytes = hyper::body::to_bytes(req.into_body()).await?;

// after: bound the body and reject framing errors as 400
use hyper::body::Body;
match hyper::body::to_bytes(req.into_body()).await {
    Ok(bytes) if bytes.len() <= MAX_BODY => Ok(bytes),
    Ok(_) => Ok(response_413()),
    Err(_) => Ok(response_400()), // includes 'invalid chunk size: overflow'
}
Defensive patterns

Strategy: try-catch

Type guard

fn is_invalid_chunk_size(err: &hyper::Error) -> bool {
    matches!(
        err.source().and_then(|s| s.downcast_ref::<std::io::Error>()).map(|io| io.kind()),
        Some(std::io::ErrorKind::InvalidData)
    )
}

Try / catch

match hyper::body::to_bytes(req.into_body()).await {
    Ok(b) if b.len() <= MAX_BODY => Ok(b),
    Ok(_) => Ok(resp_413()),
    Err(e) if is_invalid_chunk_size(&e) => Ok(resp_400()), // corrupt/abusive framing
    Err(e) => Err(e),
}

Prevention

When it happens

Trigger: The chunk-size line contains an absurdly long run of hex digits (>16) such that size.checked_mul(16)/checked_add overflows u64 (decode.rs:264-273 guarding every accumulation in read_start/read_size). Triggered by a malformed or malicious chunked body advertising a near-u64-max chunk size.

Common situations: A buggy producer emits a garbage chunk-size line; a fuzzing/attack payload with a huge hex size; a misbehaving proxy that mangles chunk framing. Benign clients never send chunk sizes anywhere near the limit, so this almost always indicates corruption or abuse.

Related errors


AI-assisted analysis of hyperium/hyper@084473f728 (2026-08-06). Data as JSON: /data/errors/60cabfcae71c2584.json. Report an issue: GitHub.