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

chunk trailers bytes over limit

Error message

chunk trailers bytes over limit

What it means

Thrown in the HTTP/1 chunked decoder via the put_u8! macro (src/proto/h1/decode.rs:281) as io::Error::new(InvalidData, "chunk trailers bytes over limit"). It fires while accumulating the trailer section of a chunked body: each appended byte is checked and, once the trailers buffer reaches the limit, the error is returned. The default limit is TRAILER_LIMIT = 16 KiB (decode.rs:25), or h1_max_header_size if configured (decode.rs:181).

Source

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

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",
            )));
        }
    };
}

struct StepArgs<'a> {
    chunk_size: &'a mut u64,
    chunk_buf: &'a mut Option<Bytes>,
    extensions_cnt: &'a mut u64,
    trailers_buf: &'a mut Option<BytesMut>,
    trailers_cnt: &'a mut usize,
    max_headers_cnt: usize,
    max_headers_bytes: usize,
}

impl ChunkedState {

View on GitHub (pinned to 084473f728)

Solutions

  1. If large trailers are legitimate, raise the trailer limit via the HTTP/1 max header size / max headers configuration on the Builder.
  2. Otherwise move that data into the message head (normal headers) or the body, and keep trailers small.
  3. On the server, reject such requests with 431 and confirm the cap matches your policy.

Example fix

// before: default 16 KiB trailer limit rejects legitimate large trailers
let mut http = hyper::server::conn::Http::new();

// after: raise the per-header/trailer size limit to fit your workload
let mut http = hyper::server::conn::Http::new();
http.max_buf_size(64 * 1024); // larger head+trailer buffer
// and/or configure h1 max header size via the Builder options exposed by your version
Defensive patterns

Strategy: validation

Validate before calling

// Enforce your own trailer-size policy before relying on hyper's 16 KiB default.
fn trailers_within_policy(headers: &HeaderMap, max: usize) -> bool {
    headers.iter().map(|(k, v)| k.as_str().len() + v.len() + 4).sum::<usize>() <= max
}

Type guard

fn is_trailers_over_limit(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) => Ok(b),
    Err(e) if is_trailers_over_limit(&e) => Ok(resp_431()), // trailers too large
    Err(e) => Err(e),
}

Prevention

When it happens

Trigger: The Trailer/TrailerLf/EndCr/EndLf states (decode.rs:327-337) append bytes with put_u8! (decode.rs:276-287); when the trailers buffer length reaches the configured max (TRAILER_LIMIT 16384 or a custom h1_max_header_size), the error fires. Triggered by a chunked body whose trailer headers exceed the cap.

Common situations: A client/server sends large trailer headers (big signature/checksum trailers); a misconfigured peer that puts real headers in trailers; an attacker abusing trailers to bypass head-size limits. Raising the trailer/header limit on the Builder raises the threshold.

Related errors


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