chenhg5/cc-connect · error

telegram: sendWithButtons: %w

Error message

telegram: sendWithButtons: %w

What it means

This wraps an error from the actual Telegram Bot API message-send performed inside SendWithButtons, after the HTML body was rendered and chunking was not needed. It indicates the sendMessage call with an inline keyboard failed — the reply context type was valid, but delivery failed.

Source

Thrown at platform/telegram/telegram.go:1322

			slog.Warn("telegram: HTML rejected by Telegram, sending as plain text",
				"method", "SendWithButtons",
				"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: first chunk with buttons, rest without
			slog.Warn("telegram: message too long, splitting into chunks",
				"method", "SendWithButtons",
				"html_len", len(html),
			)
			return p.sendChunkedWithButtons(ctx, bot, rc, html, rows)
		}
		if err != nil {
			return fmt.Errorf("telegram: sendWithButtons: %w", err)
		}
	}
	return nil
}

// DeletePreviewMessage deletes a stale preview message so the caller can send a fresh one.
func (p *Platform) DeletePreviewMessage(ctx context.Context, previewHandle any) error {
	h, ok := previewHandle.(*telegramPreviewHandle)
	if !ok {
		return fmt.Errorf("telegram: invalid preview handle type %T", previewHandle)
	}
	bot, err := p.connectedBot("delete preview")
	if err != nil {
		return err
	}
	_, err = bot.DeleteMessage(ctx, &tgbot.DeleteMessageParams{ChatID: h.chatID, MessageID: h.messageID})
	if err != nil {
		slog.Debug("telegram: delete preview message failed", "error", err)

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Read the wrapped error for the Bot API description; fix the specific violation (button callback data ≤64 bytes, valid HTML entities).
  2. Ensure user content is HTML-escaped before rendering so entity parsing cannot fail.
  3. Fall back to sendChunkedWithButtons when len(html) exceeds limits — the code already does this above; verify thresholds.
  4. Retry with backoff on 429/5xx responses.

Example fix

// before
html := fmt.Sprintf("<b>%s</b>", userText)
// after: escape to avoid 'can't parse entities'
html := "<b>" + html.EscapeString(userText) + "</b>"
Defensive patterns

Strategy: try-catch

Validate before calling

if len(content) > 4096 { /* use chunked send */ }
for _, row := range buttons { for _, b := range row { if len(b.CallbackData) > 64 { return errors.New("callback data too long") } } }

Try / catch

if err := p.sendWithButtons(ctx, bot, rc, html, rows); err != nil {
    if strings.Contains(err.Error(), "can't parse entities") { /* escape HTML and retry */ }
    return fmt.Errorf("telegram: sendWithButtons: %w", err)
}

Prevention

When it happens

Trigger: p.sendWithButtons (or the Bot API call inside it) returns err after the chunking branch: e.g. sendMessage rejects the markup, the text, or the network request fails.

Common situations: Inline keyboard rows exceeding Telegram limits (too many buttons/bad callback data >64 bytes); markdown/HTML parse error ('can't parse entities'); message text >4096 chars without chunking; network or 429 rate-limit errors.

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/a4b66b65d2cdcfbb. Report an issue: GitHub.