zeroclaw-labs/zeroclaw · error
Telegram sendPhoto failed: {err}
Error message
Telegram sendPhoto failed: {err} What it means
send_photo() reads the image from disk and uploads it as multipart sendPhoto (defaulting the part filename to photo.jpg), bailing with Telegram's body on non-2xx. Telegram is strict about photo payloads, so most rejections are format/size related.
Source
Thrown at crates/zeroclaw-channels/src/telegram.rs:3271
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("sendPhoto"))
.multipart(form)
.send()
.await?;
if !resp.status().is_success() {
let err = resp.text().await?;
anyhow::bail!("Telegram sendPhoto 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})),
"photo sent to"
);
Ok(())
}
/// Send a photo from bytes (in-memory) to a Telegram chat
pub async fn send_photo_bytes(
&self,
chat_id: &str,
thread_id: Option<&str>,
file_bytes: Vec<u8>,
file_name: &str,View on GitHub (pinned to 88bb9c8533)
Solutions
- Read the embedded `description` for the exact Bot API reason.
- Check the image decodes (`file`/`identify` on the path) and is JPEG/PNG/WebP under 10MB.
- Send oversized images as documents via send_document to preserve resolution.
- On 429, honor retry_after; on 403, stop sending to that chat.
Defensive patterns
Strategy: validation
Validate before calling
const PHOTO_LIMIT: u64 = 10 * 1024 * 1024;
let meta = tokio::fs::metadata(file_path).await?;
anyhow::ensure!(meta.len() <= PHOTO_LIMIT, "photo {}MB exceeds 10MB; send as document", meta.len() / 1024 / 1024); Type guard
fn looks_like_image(path: &Path) -> bool {
matches!(path.extension().and_then(|e| e.to_str()), Some("jpg" | "jpeg" | "png" | "webp"))
} Try / catch
if let Err(e) = channel.send_photo(chat, thread, path, caption).await {
if e.to_string().contains("413") || e.to_string().contains("too big") {
return channel.send_document(chat, thread, path, caption).await;
}
return Err(e);
} Prevention
- Send >10MB images as documents to keep full resolution.
- Confirm files are fully written and valid JPEG/PNG/WebP before upload.
- Route SVG/AVIF through a rasterization step first.
When it happens
Trigger: 400 when the bytes are not a decodable image (corrupt file, PNG renamed .jpg, SVG); 413 when the file exceeds the 10MB photo cap; 400 'chat not found' or bad thread_id; 403 blocked/kicked; 429 flood control.
Common situations: Sending screenshots that failed to finish writing before upload; image generation pipeline emitting webp/avif Telegram rejects; >10MB exports that should be sent as documents instead.
Related errors
- Telegram sendDocument failed: {err}
- Telegram sendVideo failed: {err}
- Telegram sendAudio failed: {err}
- Telegram sendVoice failed: {err}
- Telegram sendPhoto by URL failed: {err}
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/a6baff9fdc3b4185.
Report an issue: GitHub.