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

attachment Content-Length ({len} bytes) exceeds {} MB limit

Error message

attachment Content-Length ({len} bytes) exceeds {} MB limit

What it means

Before streaming the body, `download_remote_attachment` compares the response's `Content-Length` header against `WECHAT_MEDIA_MAX_BYTES` (100 MiB) and refuses downloads that would exceed the limit. This is an early-abort so oversized remote files are rejected without wasting bandwidth; the WeChat upload path cannot accept media beyond this size anyway.

Source

Thrown at crates/zeroclaw-channels/src/wechat.rs:1192

        }
        let resp = self
            .client
            .get(url)
            .timeout(API_TIMEOUT)
            .send()
            .await
            .with_context(|| format!("attachment download failed: {url}"))?;

        if !resp.status().is_success() {
            let status = resp.status();
            let body = resp.text().await.unwrap_or_default();
            anyhow::bail!("attachment download failed ({status}): {body}");
        }

        if let Some(len) = resp.content_length()
            && len > WECHAT_MEDIA_MAX_BYTES
        {
            anyhow::bail!(
                "attachment Content-Length ({len} bytes) exceeds {} MB limit",
                WECHAT_MEDIA_MAX_BYTES / (1024 * 1024)
            );
        }

        let content_type = resp
            .headers()
            .get(reqwest::header::CONTENT_TYPE)
            .and_then(|value| value.to_str().ok())
            .map(str::to_string);
        let bytes = resp.bytes().await?.to_vec();

        if bytes.len() as u64 > WECHAT_MEDIA_MAX_BYTES {
            anyhow::bail!(
                "attachment exceeds {} MB limit",
                WECHAT_MEDIA_MAX_BYTES / (1024 * 1024)
            );
        }

View on GitHub (pinned to 88bb9c8533)

Solutions

  1. Compress, trim, or transcode the media below 100 MiB (e.g. lower video bitrate/resolution) and send the smaller URL.
  2. Host the oversized file elsewhere (file share, object storage with a share link) and send the link as message text rather than as an attachment.
  3. If the Content-Length looks wrong, verify with `curl -I <url>` what the server actually declares and fix the hosting.
  4. Do not raise `WECHAT_MEDIA_MAX_BYTES` casually — the WeChat iLink upload endpoint enforces its own ceiling and 100 MiB is the client-side contract.

Example fix

# before
attachment.target = "https://cdn.example.com/meeting-recording.mkv"  # 480 MB -> error 335

# after: compress under the 100 MiB ceiling, or share a link
ffmpeg -i meeting-recording.mkv -b:v 800k meeting-recording-small.mp4  # < 100 MiB
attachment.target = "https://cdn.example.com/meeting-recording-small.mp4"
# or: send "Large file: https://cdn.example.com/meeting-recording.mkv" as plain text
Defensive patterns

Strategy: validation

Validate before calling

// check declared size before sending
async fn declared_size(client: &reqwest::Client, url: &str) -> Option<u64> {
    let resp = client.head(url).send().await.ok()?;
    resp.content_length()
}
if declared_size(&client, url).await.unwrap_or(0) > 100 * 1024 * 1024 {
    anyhow::bail!("too large for WeChat attachment; share a link instead");
}

Type guard

fn within_wechat_limit(len: u64) -> bool {
    len <= 100 * 1024 * 1024 // WECHAT_MEDIA_MAX_BYTES
}

Try / catch

match channel.send(msg_with_attachment(&url)).await {
    Err(err) if err.to_string().contains("exceeds 100 MB limit") => {
        // compress / re-host under the ceiling, or send a link in text
        let share = rehost_under_limit(&url).await?;
        channel.send(msg_with_text(&format!("File: {share}"))).await?;
    }
    other => other?,
}

Prevention

When it happens

Trigger: Sending a WeChat attachment whose `https://` target responds 2xx with `Content-Length: > 104857600`. Typical for large video/audio files, disk images, or archives hosted behind a correct server. Fires only when the server declares the size; chunked/missing headers hit the post-read check instead (error 336).

Common situations: Bots forwarding large video files or recordings; attachment URLs pointing at raw recordings/exports (e.g. meeting recordings, datasets) exceeding 100 MiB; server config changes making previously-small files huge (wrong file served); test fixtures using oversized blobs.

Related errors


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