chenhg5/cc-connect · error
telegram: send: %w
Error message
telegram: send: %w
What it means
The Telegram platform's Reply method wraps any error returned by the underlying bot API sendMessage call with the prefix "telegram: send: ". It indicates the message (as HTML) could not be delivered to Telegram. The original transport/API error is preserved via %w for errors.Is/As inspection.
Source
Thrown at platform/telegram/telegram.go:1079
slog.Warn("telegram: HTML rejected by Telegram, sending as plain text",
"method", "Reply",
"error", errMsg,
"html_prefix", truncateForLog(html, 200),
"html_len", len(html),
)
params.Text = content
params.ParseMode = ""
_, err = bot.SendMessage(ctx, params)
} else if strings.Contains(errMsg, "message is too long") {
// Handle message too long by splitting and sending as multiple messages
slog.Warn("telegram: message too long, splitting into chunks",
"method", "Reply",
"html_len", len(html),
)
return p.sendChunked(ctx, bot, rc, html)
}
if err != nil {
return fmt.Errorf("telegram: send: %w", err)
}
}
return nil
}
// Send sends a new message (not a reply)
func (p *Platform) Send(ctx context.Context, rctx any, content string) error {
rc, ok := rctx.(replyContext)
if !ok {
return fmt.Errorf("telegram: invalid reply context type %T", rctx)
}
bot, err := p.connectedBot("send")
if err != nil {
return err
}
html := core.MarkdownToSimpleHTML(content)
params := &tgbot.SendMessageParams{View on GitHub (pinned to 4000b2338a)
Solutions
- Check the wrapped cause with errors.Unwrap / errors.As to see whether it is network, auth, or a Telegram API error
- Verify the bot is a member of the target chat and the chatID in replyContext is correct
- Ensure the bot token is valid (run cc-connect doctor or call getMe)
- Retry with backoff on 429 responses; Telegram rate limits bots per chat
- Pre-check HTML length so oversized messages go through sendChunked instead of a single sendMessage
Example fix
// before
err := p.Reply(ctx, rctx, hugeMessage) // single sendMessage fails
// after
if len(html) > 4000 {
return p.sendChunked(ctx, bot, rc, html)
} Defensive patterns
Strategy: retry
Validate before calling
// check message length before sending
if len([]rune(html)) > 4096 {
return p.sendChunked(ctx, bot, rc, html)
} Try / catch
if err := p.Reply(ctx, rc, html); err != nil {
var apiErr *tgbot.Error
if errors.As(err, &apiErr) && apiErr.ResponseCode == 429 {
// wait retry-after and retry
}
return fmt.Errorf("telegram reply failed: %w", err)
} Prevention
- Keep the bot in the target chat and verify chat IDs
- Handle 429 flood limits with retry-after delays
- Chunk messages over 4096 chars before sending
- Monitor Telegram API status for outages
When it happens
Trigger: Calling Platform.Reply with a replyContext whose chat is unreachable: bot.SendMessage returns a network error, Telegram API error (chat not found, bot blocked, message too long if chunking path not taken), or rate limit.
Common situations: Bot kicked from or never added to the chat; wrong chat_id in the reply context; Telegram API downtime or local network failure; hitting the 4096-char limit when the html_len pre-check did not route to sendChunked; flood limits from many rapid replies.
Understand the failure class
Background: "API request failed": what wrapped HTTP errors from external APIs mean and how to find the real cause — this error's family across 29 libraries.
Related errors
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/ce5885ae65ba6d8f.
Report an issue: GitHub.