chenhg5/cc-connect · error
telegram: SendAudio: %w
Error message
telegram: SendAudio: %w
What it means
When both sendVoice and its sendAudio fallback fail for mp3/m4a audio, SendAudio returns a joined error "telegram: SendAudio: " containing "sendVoice failed" and "sendAudio fallback failed" via errors.Join. It means Telegram rejected the audio both as a voice note and as an audio document.
Source
Thrown at platform/telegram/telegram.go:1214
switch sendFormat {
case "ogg", "opus", "mp3", "m4a":
// Attempt these formats directly with sendVoice first.
default:
converted, err := telegramConvertAudioToOpus(ctx, audio, sendFormat)
if err != nil {
return fmt.Errorf("telegram: SendAudio: convert %s to opus: %w", sendFormat, err)
}
sendData = converted
sendFormat = "opus"
}
if err := p.sendVoice(ctx, rc, sendData, sendFormat); err != nil {
if sendFormat == "mp3" || sendFormat == "m4a" {
if fallbackErr := p.sendAudio(ctx, rc, sendData, sendFormat); fallbackErr == nil {
return nil
} else {
return fmt.Errorf(
"telegram: SendAudio: %w",
errors.Join(
fmt.Errorf("sendVoice failed: %w", err),
fmt.Errorf("sendAudio fallback failed: %w", fallbackErr),
),
)
}
}
return fmt.Errorf("telegram: SendAudio: sendVoice: %w", err)
}
return nil
}
func (p *Platform) sendVoice(ctx context.Context, rc replyContext, audio []byte, format string) error {
bot, err := p.connectedBot("send voice")
if err != nil {
return err
}View on GitHub (pinned to 4000b2338a)
Solutions
- Inspect both joined causes with errors.Is/As to see if it is 429, network, or an API rejection
- Add retry-with-backoff around SendAudio; a single flood limit can fail both paths
- Validate the mp3/m4a bytes decode correctly (e.g. ffprobe) before sending
- Prefer ogg/opus output from TTS to avoid the fallback path entirely
- Confirm bot membership and chat ID validity if both failures are chat-not-found
Example fix
// before
err := p.SendAudio(ctx, rc, audio, "mp3") // one-shot, both paths can fail
// after
var retryErr error
for i := 0; i < 3; i++ {
if retryErr = p.SendAudio(ctx, rc, audio, "mp3"); retryErr == nil {
break
}
time.Sleep(time.Duration(1<<i) * time.Second)
} Defensive patterns
Strategy: retry
Validate before calling
// validate mp3 header before sending
if len(audio) < 3 || !bytes.Equal(audio[:3], []byte{'I','D','3'}) && audio[0] != 0xFF {
return errors.New("payload does not look like mp3/m4a audio")
} Try / catch
var joinErr *telegramSendAudioError // or inspect via errors.Is
if err := p.SendAudio(ctx, rc, audio, "mp3"); err != nil {
if errors.Is(err, context.DeadlineExceeded) || isFlood(err) {
// exponential backoff retry
}
return err
} Prevention
- Prefer ogg/opus TTS output to avoid the dual-failure path
- Add exponential backoff around SendAudio
- Verify audio bytes decode with ffprobe before sending
- Check bot membership and rate limits when both voice and audio attempts fail
When it happens
Trigger: sendVoice fails (Telegram rejects mp3/m4a as voice on old API paths, network error, flood limit) AND sendAudio also fails (upload error, chat access, size limit).
Common situations: Temporary Telegram API incidents; bot flood-limited so both attempts fail; corrupt mp3/m4a payloads; bot removed from chat between attempts; oversized audio buffers.
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
- discord: send fallback: %w
- telegram: send: %w
- telegram: send image: %w
- telegram: send file: %w
- telegram: SendAudio: convert %s to opus: %w
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/dfc85d18951b8770.
Report an issue: GitHub.