{"record":{"id":"43bbbe2d80d4bc2f","repo":"chenhg5/cc-connect","slug":"weixin-empty-audio","errorCode":null,"errorMessage":"weixin: empty audio","messagePattern":"weixin: empty audio","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"platform/weixin/media_outbound.go","lineNumber":254,"sourceCode":"\text := strings.TrimPrefix(strings.ToLower(filepath.Ext(file.FileName)), \".\")\n\tswitch ext {\n\tcase \"avi\", \"m4v\", \"mkv\", \"mov\", \"mp4\", \"mpeg\", \"mpg\", \"webm\":\n\t\treturn true\n\tdefault:\n\t\treturn false\n\t}\n}\n\n// SendAudio implements core.AudioSender.\n// Weixin voice messages require AMR or SILK format. Since SILK encoding is not\n// widely supported, we convert to AMR format using ffmpeg.\nfunc (p *Platform) SendAudio(ctx context.Context, replyCtx any, audio []byte, format string) error {\n\trc, err := p.resolveReplyContext(replyCtx)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif len(audio) == 0 {\n\t\treturn fmt.Errorf(\"weixin: empty audio\")\n\t}\n\n\t// Convert to AMR format if not already AMR\n\tsendData := audio\n\tsendFormat := strings.ToLower(strings.TrimSpace(format))\n\tif sendFormat == \"\" {\n\t\tsendFormat = \"wav\" // TTS typically outputs WAV\n\t}\n\tif sendFormat != \"amr\" {\n\t\tconverted, err := core.ConvertAudioToAMR(ctx, audio, sendFormat)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"weixin: convert %s to AMR: %w\", sendFormat, err)\n\t\t}\n\t\tsendData = converted\n\t\tsendFormat = \"amr\"\n\t}\n\n\tslog.Debug(\"weixin: audio converted\", \"format\", sendFormat, \"size\", len(sendData))","sourceCodeStart":236,"sourceCodeEnd":272,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/platform/weixin/media_outbound.go#L236-L272","documentation":"Validation guard in Weixin SendAudio: the audio byte slice has zero length after reply-context resolution, so there is no voice data to convert to AMR and send.","triggerScenarios":"Calling SendAudio with audio == nil or audio == []byte{} (e.g. TTS/record step produced no output).","commonSituations":"Text-to-speech engine silently produced an empty buffer; microphone recording captured zero bytes; conversion pipeline failed upstream and returned empty data.","solutions":["Check len(audio) > 0 before calling SendAudio.","Fix the TTS/recording step that produced empty audio and verify its output size.","Pass a non-empty format or leave blank — the empty-audio error is purely about the byte payload, not the format."],"exampleFix":"// before\nwav, _ := tts.Synthesize(text) // error ignored\np.SendAudio(ctx, rc, wav, \"wav\") // weixin: empty audio\n// after\nwav, err := tts.Synthesize(text)\nif err != nil || len(wav) == 0 { return fmt.Errorf(\"tts: %w\", err) }","handlingStrategy":"validation","validationCode":"if len(audio) == 0 { return errors.New(\"audio payload is empty; skipping send\") }","typeGuard":null,"tryCatchPattern":"if err := p.SendAudio(ctx, rc, audio, format); err != nil && strings.Contains(err.Error(), \"empty audio\") { log.Error(\"TTS/recording produced empty audio\") }","preventionTips":["Verify TTS/recorder output length before sending","Propagate synthesis errors rather than returning empty buffers","Test the audio pipeline end-to-end with fixture data"],"tags":["weixin","audio","validation","empty-data"],"backgroundTag":"empty-required-field","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"}