{"record":{"id":"2a3a2b734b10f82e","repo":"zeroclaw-labs/zeroclaw","slug":"audio-download-exceeds-byte-limit","errorCode":null,"errorMessage":"audio download exceeds {} byte limit","messagePattern":"audio download exceeds (.+?) byte limit","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"warning","filePath":"crates/zeroclaw-channels/src/lark.rs","lineNumber":1913,"sourceCode":"            }\n            Err(err) => {\n                ::zeroclaw_log::record!(\n                    WARN,\n                    ::zeroclaw_log::Event::new(module_path!(), ::zeroclaw_log::Action::Note)\n                        .with_outcome(::zeroclaw_log::EventOutcome::Unknown)\n                        .with_attrs(::serde_json::json!({\"err\": err.to_string()})),\n                    \"failed to resolve bot open_id: ; mention_only group messages will be ignored\"\n                );\n            }\n        }\n    }\n\n    async fn stream_audio_bytes(mut resp: reqwest::Response) -> anyhow::Result<Vec<u8>> {\n        let mut body = Vec::new();\n        while let Some(chunk) = resp.chunk().await? {\n            body.extend_from_slice(&chunk);\n            if body.len() as u64 > MAX_LARK_AUDIO_BYTES {\n                anyhow::bail!(\"audio download exceeds {} byte limit\", MAX_LARK_AUDIO_BYTES);\n            }\n        }\n        Ok(body)\n    }\n\n    async fn download_audio_resource(\n        &self,\n        message_id: &str,\n        file_key: &str,\n    ) -> anyhow::Result<(Vec<u8>, String)> {\n        let url = format!(\n            \"{}/im/v1/messages/{message_id}/resources/{file_key}?type=file\",\n            self.api_base()\n        );\n        let token = self.get_tenant_access_token().await?;\n        let resp = self\n            .http_client()\n            .get(&url)","sourceCodeStart":1895,"sourceCodeEnd":1931,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-channels/src/lark.rs#L1895-L1931","documentation":"stream_audio_bytes downloads a Lark audio resource chunk by chunk and aborts as soon as the accumulated bytes exceed MAX_LARK_AUDIO_BYTES, a compile-time constant of 25 MiB (25 * 1024 * 1024, lark.rs:23). The limit protects the process from buffering unbounded downloads in memory, since the whole body is collected into a Vec<u8> for transcription. It is not configurable at runtime.","triggerScenarios":"An inbound voice/audio message whose resource exceeds 25 MiB: very long voice notes, high-bitrate audio files, or a file_key/content_type mapping that routes a large video into the audio download path.","commonSituations":"Users forwarding long recordings, users sending audio files (m4a/mp3) instead of recorded voice notes, or upstream content-type changes reclassifying large media as audio.","solutions":["Treat as expected degradation: skip transcription for oversized audio and, if desired, notify the user.","If the pipeline genuinely needs larger audio, raise the const MAX_LARK_AUDIO_BYTES in crates/zeroclaw-channels/src/lark.rs and rebuild, keeping in mind the full body is held in memory.","Check Content-Length before streaming so oversized resources are rejected before the download starts.","Verify the file_key/content_type mapping is not misrouting large non-audio media into the audio path."],"exampleFix":"// before (crates/zeroclaw-channels/src/lark.rs:23)\nconst MAX_LARK_AUDIO_BYTES: u64 = 25 * 1024 * 1024;\n\n// after (raises the in-memory cap; whole body is still buffered)\nconst MAX_LARK_AUDIO_BYTES: u64 = 50 * 1024 * 1024;","handlingStrategy":"validation","validationCode":"// Reject oversized downloads before streaming anything\nif let Some(len) = resp.content_length() {\n    anyhow::ensure!(\n        len <= MAX_LARK_AUDIO_BYTES,\n        \"lark audio content-length {len} exceeds {} cap; skipping download\",\n        MAX_LARK_AUDIO_BYTES\n    );\n}","typeGuard":"fn is_audio_size_error(err: &anyhow::Error) -> bool {\n    err.to_string().contains(\"audio download exceeds\")\n}","tryCatchPattern":"if is_audio_size_error(&e) {\n    // expected degradation, not a fault: skip transcription, keep processing the message\n    tracing::warn!(error = %e, \"oversized lark audio; skipping transcription\");\n    return Ok(());\n}","preventionTips":["Check Content-Length before downloading large media.","Keep transcription optional: audio failure must not fail the whole message turn.","If raising the cap, size heap headroom for the full buffered Vec<u8>."],"tags":["lark","audio","size-limit","streaming","transcription"],"backgroundTag":"download-size-limit-exceeded","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}