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
- Compress or downscale the asset (re-encode video, resize images, PDF-compress) below 10 MiB
- Split large documents into parts, or trim logs before attaching
- 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
- Compress pipeline outputs (re-encode video, resize images) at generation time, not at send time
- Alert when generated artifacts approach 10 MiB so sends fail before QQ is involved
- For large reports, publish over https and reference the URL in the marker instead of attaching bytes
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
- Discord send message with files failed ({status}): {err}
- QQ upload media failed ({status}): {err}
- QQ send media message failed ({status}): {err}
- QQ attachment path not found: {target}
- QQ channel requires the `channel-qq` feature
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/ee81c16e1eba0004.
Report an issue: GitHub.