{"record":{"id":"47bb3e56a8863329","repo":"chenhg5/cc-connect","slug":"sendvoice-failed-w","errorCode":null,"errorMessage":"sendVoice failed: %w","messagePattern":"sendVoice failed: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"platform/telegram/telegram.go","lineNumber":1217,"sourceCode":"\t\t// Attempt these formats directly with sendVoice first.\n\tdefault:\n\t\tconverted, err := telegramConvertAudioToOpus(ctx, audio, sendFormat)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"telegram: SendAudio: convert %s to opus: %w\", sendFormat, err)\n\t\t}\n\t\tsendData = converted\n\t\tsendFormat = \"opus\"\n\t}\n\n\tif err := p.sendVoice(ctx, rc, sendData, sendFormat); err != nil {\n\t\tif sendFormat == \"mp3\" || sendFormat == \"m4a\" {\n\t\t\tif fallbackErr := p.sendAudio(ctx, rc, sendData, sendFormat); fallbackErr == nil {\n\t\t\t\treturn nil\n\t\t\t} else {\n\t\t\t\treturn fmt.Errorf(\n\t\t\t\t\t\"telegram: SendAudio: %w\",\n\t\t\t\t\terrors.Join(\n\t\t\t\t\t\tfmt.Errorf(\"sendVoice failed: %w\", err),\n\t\t\t\t\t\tfmt.Errorf(\"sendAudio fallback failed: %w\", fallbackErr),\n\t\t\t\t\t),\n\t\t\t\t)\n\t\t\t}\n\t\t}\n\t\treturn fmt.Errorf(\"telegram: SendAudio: sendVoice: %w\", err)\n\t}\n\treturn nil\n}\n\nfunc (p *Platform) sendVoice(ctx context.Context, rc replyContext, audio []byte, format string) error {\n\tbot, err := p.connectedBot(\"send voice\")\n\tif err != nil {\n\t\treturn err\n\t}\n\tparams := &tgbot.SendVoiceParams{\n\t\tChatID:          rc.chatID,\n\t\tMessageThreadID: rc.threadID,","sourceCodeStart":1199,"sourceCodeEnd":1235,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/platform/telegram/telegram.go#L1199-L1235","documentation":"This error is wrapped inside the combined error returned when the Telegram platform tries to send a voice note via SendVoice and it fails, then falls back to SendAudio, which also fails. The platform joins both underlying errors with errors.Join under a 'telegram: SendAudio:' prefix so the caller can see the full failure chain. It means the Bot API sendVoice call itself rejected or could not deliver the audio payload.","triggerScenarios":"p.sendVoice(ctx, rc, audioData, sendFormat) returns an error (Bot API error, network failure, bad format/fileID) AND the p.sendAudio fallback also errors; both are joined and returned from the voice-sending path of the audio-sending method.","commonSituations":"Sending OGG/OPUS voice notes with an unsupported container that Telegram rejects; network interruption to api.telegram.org; bot lacking permission to post in the chat; file exceeding Telegram's 50 MB bot upload limit.","solutions":["Check the joined fallbackErr (sendAudio fallback failed) for the Bot API description — it usually names the real cause (e.g. 'wrong file identifier/HTTP URL specified').","Verify the audio is a valid OGG encoded with OPUS codec for sendVoice; re-encode with ffmpeg -c:a libopus if not.","Confirm the bot is a member of the target chat with permission to send messages.","Retry on transient network errors; reduce file size below 50 MB if applicable."],"exampleFix":"// before: single attempt, opaque failure\nerr := p.sendVoice(ctx, rc, data, format)\n// after: inspect joined errors to find root cause\nvar joined interface{ Unwrap() []error }\nif errors.As(err, &joined) { for _, e := range joined { log.Println(e) } }","handlingStrategy":"fallback","validationCode":"if len(audio) > 50*1024*1024 { return errors.New(\"file exceeds 50 MB bot upload limit\") }","typeGuard":null,"tryCatchPattern":"if err := p.sendVoice(ctx, rc, data, format); err != nil {\n    if fbErr := p.sendAudio(ctx, rc, data, format); fbErr != nil {\n        return errors.Join(err, fbErr) // inspect both for root cause\n    }\n}","preventionTips":["Encode voice notes as OGG/Opus before sending","Keep uploads under Telegram's 50 MB bot limit","Check bot chat permissions before media sends","Retry transient network errors with backoff"],"tags":["telegram","bot-api","audio-upload","network"],"backgroundTag":"api-request-failed","analyzedSha":"4000b2338aa6e850c99df54f8b0ed6ed7460b401","analyzedAt":"2026-09-06T11:45:09.575Z","contentChangedAt":"2026-09-06T11:45:09.575Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}