{"record":{"id":"2a79b9225458c82c","repo":"zeroclaw-labs/zeroclaw","slug":"telegram-sendaudio-failed-err","errorCode":null,"errorMessage":"Telegram sendAudio failed: {err}","messagePattern":"Telegram sendAudio failed: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/zeroclaw-channels/src/telegram.rs","lineNumber":3413,"sourceCode":"\n        if let Some(tid) = thread_id {\n            form = form.text(\"message_thread_id\", tid.to_string());\n        }\n\n        if let Some(cap) = caption {\n            form = form.text(\"caption\", cap.to_string());\n        }\n\n        let resp = self\n            .http_client()\n            .post(self.api_url(\"sendAudio\"))\n            .multipart(form)\n            .send()\n            .await?;\n\n        if !resp.status().is_success() {\n            let err = resp.text().await?;\n            anyhow::bail!(\"Telegram sendAudio failed: {err}\");\n        }\n\n        ::zeroclaw_log::record!(\n            INFO,\n            ::zeroclaw_log::Event::new(module_path!(), ::zeroclaw_log::Action::Note)\n                .with_attrs(::serde_json::json!({\"chat_id\": chat_id, \"file_name\": file_name})),\n            \"audio sent to\"\n        );\n        Ok(())\n    }\n\n    /// Send a voice message to a Telegram chat\n    pub async fn send_voice(\n        &self,\n        chat_id: &str,\n        thread_id: Option<&str>,\n        file_path: &Path,\n        caption: Option<&str>,","sourceCodeStart":3395,"sourceCodeEnd":3431,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-channels/src/telegram.rs#L3395-L3431","documentation":"send_audio() uploads an audio file as multipart sendAudio and bails with Telegram's response body on non-2xx. Audio expects a playable music track (MP3/M4A with metadata), and errors commonly stem from format mismatches or chat permissions.","triggerScenarios":"413 when audio exceeds the 50MB cap; 400 when the bytes are not MP3/M4A (e.g. raw Opus or WAV sent as audio); 400 chat not found / invalid thread_id; 403 blocked/kicked; 429 flood control.","commonSituations":"Sending TTS output meant as a voice note (OGG/Opus) through sendAudio instead of sendVoice; large podcast/wav files; chat permission lost between queueing and delivery.","solutions":["Read the embedded `description` first.","Ensure the payload is MP3/M4A; OGG/Opus speech belongs to sendVoice.","Check size against 50MB and re-encode if needed.","On 403 stop sending to the chat; on 429 honor retry_after."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"const AUDIO_LIMIT: u64 = 50 * 1024 * 1024;\nlet meta = tokio::fs::metadata(file_path).await?;\nanyhow::ensure!(meta.len() <= AUDIO_LIMIT, \"audio {}MB exceeds 50MB\", meta.len() / 1024 / 1024);\nanyhow::ensure!(!matches!(path.extension().and_then(|e| e.to_str()), Some(\"ogg\" | \"opus\")), \"speech OGG/Opus belongs to sendVoice, not sendAudio\");","typeGuard":"fn is_music_track(path: &Path) -> bool {\n    matches!(path.extension().and_then(|e| e.to_str()), Some(\"mp3\" | \"m4a\"))\n}","tryCatchPattern":"if !is_music_track(path) {\n    return channel.send_voice(chat, thread, path, None).await;\n}\nchannel.send_audio(chat, thread, path, caption).await?;","preventionTips":["Reserve sendAudio for MP3/M4A music tracks; use sendVoice for OGG/Opus speech.","Validate size (50MB) and codec before upload.","On 429 honor retry_after; on 403 stop sending to that chat."],"tags":["telegram","sendaudio","multipart","upload","audio"],"backgroundTag":"telegram-file-upload-failed","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}