{"record":{"id":"d7e60595a6b624e4","repo":"chenhg5/cc-connect","slug":"send-audio-w","errorCode":null,"errorMessage":"send audio: %w","messagePattern":"send audio: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/engine.go","lineNumber":15893,"sourceCode":"\t\treturn fmt.Errorf(\"text exceeds max_text_len (%d > %d)\", utf8.RuneCountInString(text), e.tts.MaxTextLen)\n\t}\n\tas, ok := p.(AudioSender)\n\tif !ok {\n\t\treturn fmt.Errorf(\"platform %s does not support audio sending\", p.Name())\n\t}\n\tslog.Info(\"tts: starting synthesis\", \"voice\", e.tts.Voice, \"speed\", e.tts.Speed, \"text_len\", len(text))\n\topts := TTSSynthesisOpts{\n\t\tVoice:        e.tts.Voice,\n\t\tLanguageType: e.tts.LanguageType,\n\t\tSpeed:        e.tts.Speed,\n\t}\n\taudioData, format, err := e.tts.TTS.Synthesize(e.ctx, StripMarkdown(text), opts)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"synthesize: %w\", err)\n\t}\n\tslog.Info(\"tts: synthesis successful\", \"format\", format, \"audio_size\", len(audioData))\n\tif err := as.SendAudio(e.ctx, replyCtx, audioData, format); err != nil {\n\t\treturn fmt.Errorf(\"send audio: %w\", err)\n\t}\n\tslog.Info(\"tts: audio sent successfully\", \"platform\", p.Name())\n\treturn nil\n}\n\n// ──────────────────────────────────────────────────────────────\n// Bot-to-bot relay\n// ──────────────────────────────────────────────────────────────\n\ntype platformNameOnly struct {\n\tname string\n}\n\nfunc (p platformNameOnly) Name() string                           { return p.name }\nfunc (platformNameOnly) Start(MessageHandler) error               { return nil }\nfunc (platformNameOnly) Reply(context.Context, any, string) error { return nil }\nfunc (platformNameOnly) Send(context.Context, any, string) error  { return nil }\nfunc (platformNameOnly) Stop() error                              { return nil }","sourceCodeStart":15875,"sourceCodeEnd":15911,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/core/engine.go#L15875-L15911","documentation":"cc-connect wraps failures from the platform adapter's SendAudio call (delivering synthesized TTS audio to the messaging platform) with the 'send audio: %w' prefix. The TTS synthesis itself succeeded; the failure occurs while transmitting the audio bytes to the platform (e.g. Feishu, Telegram). The platform-specific cause is preserved via %w.","triggerScenarios":"After successful Synthesize, as.SendAudio(e.ctx, replyCtx, audioData, format) returns an error — the platform API rejects the upload (auth token expired, file too large, unsupported audio format for that platform, network failure, or the chat/message target is invalid).","commonSituations":"Platform bot token expired or rotated; audio file exceeds the platform's upload size limit; audio format from TTS (e.g. mp3) not accepted by the platform; chat ID no longer valid (user blocked bot); transient network failure during upload.","solutions":["Inspect the wrapped cause for the platform-specific failure (auth vs size vs format)","Re-authenticate or refresh the platform bot token in config.toml","Check the platform's max audio/file size and the produced audio_size in the preceding log line","Convert the TTS output to a format the platform accepts (e.g. opus/ogg for Telegram voice)","Retry — upload failures are often transient"],"exampleFix":"// before\nif err := as.SendAudio(e.ctx, replyCtx, audioData, format); err != nil {\n    return fmt.Errorf(\"send audio: %w\", err)\n}\n// after\nif err := as.SendAudio(e.ctx, replyCtx, audioData, format); err != nil {\n    slog.Warn(\"tts: audio send failed, falling back to text\", \"platform\", p.Name(), \"error\", err)\n    if ferr := e.replyText(replyCtx, text); ferr != nil {\n        return fmt.Errorf(\"send audio: %w (text fallback also failed: %v)\", err, ferr)\n    }\n    return nil\n}","handlingStrategy":"fallback","validationCode":"// check platform capability before attempting audio\nif _, ok := as.(interface{ SendAudio(ctx context.Context, rc ReplyContext, data []byte, format string) error }); !ok {\n    return e.replyText(replyCtx, text)\n}","typeGuard":null,"tryCatchPattern":"if err := as.SendAudio(e.ctx, replyCtx, audioData, format); err != nil {\n    slog.Warn(\"send audio failed; falling back to text\", \"platform\", p.Name(), \"error\", err)\n    return e.replyText(replyCtx, text)\n}","preventionTips":["Confirm the target platform supports audio and its size/format limits before enabling TTS","Keep platform bot tokens refreshed and validated at startup","Cap TTS audio length to stay under the smallest platform limit","Implement text fallback so users always get a reply"],"tags":["tts","audio-upload","platform-api","go"],"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"}