{"record":{"id":"ee81c16e1eba0004","repo":"zeroclaw-labs/zeroclaw","slug":"qq-attachment-too-large-bytes-max-targe","errorCode":null,"errorMessage":"QQ attachment too large ({} bytes, max {}): {target}","messagePattern":"QQ attachment too large \\((.+?) bytes, max (.+?)\\): (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/zeroclaw-channels/src/qq.rs","lineNumber":975,"sourceCode":"                    recipient,\n                    attachment.kind,\n                    Some(target),\n                    None,\n                    file_name.as_deref(),\n                )\n                .await?;\n            self.send_media_message(recipient, &file_info, in_reply_to)\n                .await?;\n        } else {\n            // Local file upload\n            let path = Path::new(target);\n            if !path.exists() {\n                anyhow::bail!(\"QQ attachment path not found: {target}\");\n            }\n\n            let metadata = tokio::fs::metadata(path).await?;\n            if metadata.len() > QQ_MAX_UPLOAD_BYTES {\n                anyhow::bail!(\n                    \"QQ attachment too large ({} bytes, max {}): {target}\",\n                    metadata.len(),\n                    QQ_MAX_UPLOAD_BYTES\n                );\n            }\n\n            let file_bytes = tokio::fs::read(path).await?;\n            let (scope_label, target_id) = Self::resolve_recipient(recipient);\n            let scope = if scope_label == \"groups\" {\n                \"group\"\n            } else {\n                \"c2c\"\n            };\n            let cache_key = Self::upload_cache_key(&file_bytes, scope, &target_id, attachment.kind);\n\n            // Check upload cache\n            if let Some(cached_file_info) = self.get_cached_upload(&cache_key).await {\n                ::zeroclaw_log::record!(","sourceCodeStart":957,"sourceCodeEnd":993,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-channels/src/qq.rs#L957-L993","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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)"],"exampleFix":"# before\n[VIDEO:/tmp/demo-recording.mov]        # 48 MB -> bail: attachment too large\n\n# after\n# re-encode first: ffmpeg -i demo-recording.mov -b:v 1M demo.mp4\n[VIDEO:/tmp/demo.mp4]","handlingStrategy":"validation","validationCode":"// Enforce QQ's 10 MiB cap (QQ_MAX_UPLOAD_BYTES) before sending:\nconst QQ_MAX_UPLOAD_BYTES: u64 = 10 * 1024 * 1024;\n\nasync fn attachment_within_qq_limit(target: &str) -> anyhow::Result<()> {\n    if target.starts_with(\"http://\") || target.starts_with(\"https://\") {\n        return Ok(()); // remote targets skip the local size gate\n    }\n    let len = tokio::fs::metadata(target).await?.len();\n    anyhow::ensure!(len <= QQ_MAX_UPLOAD_BYTES, \"{target} is {len} bytes, over {} cap\", QQ_MAX_UPLOAD_BYTES);\n    Ok(())\n}","typeGuard":null,"tryCatchPattern":"match ch.send(&msg).await {\n    Err(e) if e.to_string().starts_with(\"QQ attachment too large\") => {\n        // Deterministic: compress/split the file or switch to an https URL target; retry cannot help.\n    }\n    rest => rest?,\n}","preventionTips":["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"],"tags":["qq","attachments","file-size","upload-limit"],"backgroundTag":"file-size-limit-exceeded","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}