zeroclaw-labs/zeroclaw · error

QQ attachment too large ({} bytes, max {}): {target}

Error message

QQ attachment too large ({} bytes, max {}): {target}

What it means

send_attachment checks tokio::fs::metadata against QQ_MAX_UPLOAD_BYTES (10 MiB, qq.rs:19) — QQ's hard cap for media uploads — and bails with the actual byte count, the cap, and the target path. The check happens after the existence check and before any network call, so no bytes are transmitted for oversized files.

Source

Thrown at crates/zeroclaw-channels/src/qq.rs:975

                    recipient,
                    attachment.kind,
                    Some(target),
                    None,
                    file_name.as_deref(),
                )
                .await?;
            self.send_media_message(recipient, &file_info, in_reply_to)
                .await?;
        } else {
            // Local file upload
            let path = Path::new(target);
            if !path.exists() {
                anyhow::bail!("QQ attachment path not found: {target}");
            }

            let metadata = tokio::fs::metadata(path).await?;
            if metadata.len() > QQ_MAX_UPLOAD_BYTES {
                anyhow::bail!(
                    "QQ attachment too large ({} bytes, max {}): {target}",
                    metadata.len(),
                    QQ_MAX_UPLOAD_BYTES
                );
            }

            let file_bytes = tokio::fs::read(path).await?;
            let (scope_label, target_id) = Self::resolve_recipient(recipient);
            let scope = if scope_label == "groups" {
                "group"
            } else {
                "c2c"
            };
            let cache_key = Self::upload_cache_key(&file_bytes, scope, &target_id, attachment.kind);

            // Check upload cache
            if let Some(cached_file_info) = self.get_cached_upload(&cache_key).await {
                ::zeroclaw_log::record!(

View on GitHub (pinned to 88bb9c8533)

Solutions

  1. Compress or downscale the asset (re-encode video, resize images, PDF-compress) below 10 MiB
  2. Split large documents into parts, or trim logs before attaching
  3. Host the file over https and reference the URL instead — remote targets skip the local size gate (subject to QQ-side limits)

Example fix

# before
[VIDEO:/tmp/demo-recording.mov]        # 48 MB -> bail: attachment too large

# after
# re-encode first: ffmpeg -i demo-recording.mov -b:v 1M demo.mp4
[VIDEO:/tmp/demo.mp4]
Defensive patterns

Strategy: validation

Validate before calling

// Enforce QQ's 10 MiB cap (QQ_MAX_UPLOAD_BYTES) before sending:
const QQ_MAX_UPLOAD_BYTES: u64 = 10 * 1024 * 1024;

async fn attachment_within_qq_limit(target: &str) -> anyhow::Result<()> {
    if target.starts_with("http://") || target.starts_with("https://") {
        return Ok(()); // remote targets skip the local size gate
    }
    let len = tokio::fs::metadata(target).await?.len();
    anyhow::ensure!(len <= QQ_MAX_UPLOAD_BYTES, "{target} is {len} bytes, over {} cap", QQ_MAX_UPLOAD_BYTES);
    Ok(())
}

Try / catch

match ch.send(&msg).await {
    Err(e) if e.to_string().starts_with("QQ attachment too large") => {
        // Deterministic: compress/split the file or switch to an https URL target; retry cannot help.
    }
    rest => rest?,
}

Prevention

When it happens

Trigger: A local attachment referenced by a marker ([IMAGE:], [VIDEO:], [AUDIO:], [DOCUMENT:]) whose file size exceeds 10 * 1024 * 1024 bytes; screen recordings, PDFs, and uncompressed images are the usual offenders.

Common situations: Agent pipelines emitting full-resolution screenshots or raw video; log/report files growing past 10 MiB over time; switching a marker from a remote URL to a local file without re-checking size.

Related errors


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