zeroclaw-labs/zeroclaw · error

Telegram sendVideo failed: {err}

Error message

Telegram sendVideo failed: {err}

What it means

send_video() uploads a video file as multipart sendVideo and bails with Telegram's response body on non-2xx. Videos have the strictest limits and encoding expectations of the media methods, so most rejections are size, codec, or chat-permission related.

Source

Thrown at crates/zeroclaw-channels/src/telegram.rs:3364

        if let Some(tid) = thread_id {
            form = form.text("message_thread_id", tid.to_string());
        }

        if let Some(cap) = caption {
            form = form.text("caption", cap.to_string());
        }

        let resp = self
            .http_client()
            .post(self.api_url("sendVideo"))
            .multipart(form)
            .send()
            .await?;

        if !resp.status().is_success() {
            let err = resp.text().await?;
            anyhow::bail!("Telegram sendVideo failed: {err}");
        }

        ::zeroclaw_log::record!(
            INFO,
            ::zeroclaw_log::Event::new(module_path!(), ::zeroclaw_log::Action::Note)
                .with_attrs(::serde_json::json!({"chat_id": chat_id, "file_name": file_name})),
            "video sent to"
        );
        Ok(())
    }

    /// Send an audio file to a Telegram chat
    pub async fn send_audio(
        &self,
        chat_id: &str,
        thread_id: Option<&str>,
        file_path: &Path,
        caption: Option<&str>,

View on GitHub (pinned to 88bb9c8533)

Solutions

  1. Read the embedded `description` for the exact reason.
  2. Check size against 50MB and re-encode (ffmpeg -c:v libx264 -movflags +faststart) when Telegram rejects the container.
  3. Verify chat_id/thread_id and stop sending on 403 blocked/kicked.
  4. Honor retry_after on 429 and resend once.
Defensive patterns

Strategy: try-catch

Validate before calling

const VIDEO_LIMIT: u64 = 50 * 1024 * 1024;
let meta = tokio::fs::metadata(file_path).await?;
anyhow::ensure!(meta.len() <= VIDEO_LIMIT, "video {}MB exceeds 50MB", meta.len() / 1024 / 1024);

Type guard

fn is_video_rejected_for_size(err: &anyhow::Error) -> bool {
    let s = err.to_string();
    s.contains("413") || s.contains("file is too big")
}

Try / catch

if let Err(e) = channel.send_video(chat, thread, path, caption).await {
    if is_video_rejected_for_size(&e) {
        return channel.send_document(chat, thread, path, caption).await; // preserve as file
    }
    return Err(e);
}

Prevention

When it happens

Trigger: 413 when the video exceeds the 50MB bot-upload cap; 400 when the container/codec is not streamable H.264/MPEG4 Telegram accepts; 400 'chat not found' or a thread_id that is not a forum topic; 403 blocked/kicked; 429 flood control.

Common situations: Screen recordings over 50MB; HEVC/odd-container exports from generation tools; sending into a chat the bot was removed from while a queued reply flushed.

Related errors


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