zeroclaw-labs/zeroclaw · error · anyhow::Error

response body content length {content_length} exceeds {max_b

Error message

response body content length {content_length} exceeds {max_bytes}-byte limit

What it means

read_response_body_limited (shared by the Mattermost and QQ channels) enforces a byte cap on API response bodies. Before reading anything, it compares the Content-Length header against max_bytes and bails immediately when the declared size is over the limit, so an oversized body is rejected without transferring it.

Source

Thrown at crates/zeroclaw-channels/src/util.rs:52

    if max_bytes >= s.len() {
        return s.len();
    }
    let mut end = max_bytes;
    while end > 0 && !s.is_char_boundary(end) {
        end -= 1;
    }
    end
}

#[cfg(any(feature = "channel-mattermost", feature = "channel-qq"))]
pub(crate) async fn read_response_body_limited(
    mut response: reqwest::Response,
    max_bytes: u64,
) -> anyhow::Result<Vec<u8>> {
    if let Some(content_length) = response.content_length()
        && content_length > max_bytes
    {
        anyhow::bail!(
            "response body content length {content_length} exceeds {max_bytes}-byte limit"
        );
    }

    let mut body = Vec::new();

    while let Some(chunk) = response.chunk().await? {
        let chunk_len = u64::try_from(chunk.len()).unwrap_or(u64::MAX);
        let next_len = u64::try_from(body.len())
            .unwrap_or(u64::MAX)
            .saturating_add(chunk_len);
        if next_len > max_bytes {
            anyhow::bail!("response body exceeds {max_bytes}-byte limit");
        }
        body.extend_from_slice(&chunk);
    }

    Ok(body)

View on GitHub (pinned to 88bb9c8533)

Solutions

  1. Avoid routing oversized resources through the bounded reader: fetch large attachments via a dedicated download path with its own higher cap.
  2. If the payload is legitimately large and trusted, call a reader with a higher max_bytes instead of bypassing bounds entirely.
  3. Confirm the server is not mis-declaring Content-Length (compare with actual body size).
Defensive patterns

Strategy: try-catch

Try / catch

match read_response_body_limited(response, max_bytes).await {
    Ok(body) => Ok(body),
    Err(err) if err.to_string().contains("content length") => {
        // Declared oversize: not retryable with the same cap. Route the
        // resource to a dedicated download path with its own limit.
        Err(err.context("payload over channel body cap — use a bounded download path"))
    }
    Err(err) => Err(err),
}

Prevention

When it happens

Trigger: A Mattermost/QQ API response whose Content-Length header exceeds the caller-supplied cap: fetching a very large file/attachment payload, an oversized channel export, or a server mis-declaring length. The unit tests exercise exactly this declared-oversize path.

Common situations: Downloading attachments or history blobs through a channel client that was sized for ordinary message JSON. A peer server returning an unexpectedly huge serialized payload trips the guard that exists to bound memory use.

Related errors


AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23). Data as JSON: /api/errors/8df68ce1b6cbec41. Report an issue: GitHub.