{"record":{"id":"c5e12114e7cad6e2","repo":"chenhg5/cc-connect","slug":"s-build-audio-message-w","errorCode":null,"errorMessage":"%s: build audio message: %w","messagePattern":"(.+?): build audio message: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"platform/feishu/feishu.go","lineNumber":5512,"sourceCode":"\t\t\tif !uploadResp.Success() {\n\t\t\t\treturn fmt.Errorf(\"%s: upload audio code=%d msg=%s\", p.tag(), uploadResp.Code, uploadResp.Msg)\n\t\t\t}\n\t\t\treturn nil\n\t\t})\n\t}); err != nil {\n\t\treturn err\n\t}\n\tif uploadResp.Data == nil || uploadResp.Data.FileKey == nil {\n\t\treturn fmt.Errorf(\"%s: upload audio: no file_key returned\", p.tag())\n\t}\n\tfileKey := *uploadResp.Data.FileKey\n\n\tslog.Debug(p.tag()+\": audio uploaded\", \"file_key\", fileKey, \"format\", format, \"size\", len(audio))\n\n\taudioMsg := larkim.MessageAudio{FileKey: fileKey}\n\taudioContent, err := audioMsg.String()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"%s: build audio message: %w\", p.tag(), err)\n\t}\n\n\t// Diagnostic for QA-reported intermittent \"audio rendered as file\" in\n\t// P2P reply mode (see internal task t-20260615-cqjbk1). Tracking the\n\t// API path lets operators correlate Feishu client renders to whether\n\t// we used Reply (in-thread) or Create (new message) when issues\n\t// recur. The Reply path has historically had narrower MsgType\n\t// support on some Feishu desktop client versions.\n\tif p.shouldUseThreadOrReplyAPI(rc) {\n\t\tslog.Debug(p.tag()+\": SendAudio using Reply API\",\n\t\t\t\"file_key\", fileKey, \"msg_id\", rc.messageID, \"format\", format)\n\t} else {\n\t\tslog.Debug(p.tag()+\": SendAudio using Create API\",\n\t\t\t\"file_key\", fileKey, \"chat_id\", rc.chatID, \"format\", format)\n\t}\n\n\treturn p.sendMediaMessage(ctx, rc, larkim.MsgTypeAudio, audioContent)\n}","sourceCodeStart":5494,"sourceCodeEnd":5530,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/platform/feishu/feishu.go#L5494-L5530","documentation":"SendAudio serializes the larkim.MessageAudio struct (containing the uploaded file_key) into the message JSON content via audioMsg.String(). This error wraps a failure of that serialization. It is rare — it only fires if the audio message struct cannot be marshalled to Feishu's content JSON, usually due to an SDK version mismatch or an empty/invalid file_key.","triggerScenarios":"audioMsg.String() returns a non-nil error: nil or empty FileKey produced an invalid content payload, or the installed lark SDK's MessageAudio.String has a marshalling bug/changed contract.","commonSituations":"A previous step silently produced an empty file_key (e.g. altered validation removed the 1237 check); SDK upgrade changed MessageAudio's schema; hand-patched fork of the SDK.","solutions":["Verify fileKey is non-empty before building the message (re-add the 1237 guard if removed)","Pin the lark SDK version known to work with this platform version","Rebuild from a clean checkout to eliminate patched SDK code","Log fileKey and the wrapped error to confirm which field is invalid"],"exampleFix":"// before\naudioMsg := larkim.MessageAudio{FileKey: fileKey}\naudioContent, err := audioMsg.String()\n// after\nif fileKey == \"\" { return fmt.Errorf(\"%s: empty file_key before building audio message\", p.tag()) }\naudioMsg := larkim.MessageAudio{FileKey: fileKey}\naudioContent, err := audioMsg.String()","handlingStrategy":"validation","validationCode":"if fileKey == \"\" { return errors.New(\"cannot build audio message: empty file_key\") }","typeGuard":null,"tryCatchPattern":"audioContent, err := audioMsg.String()\nif err != nil {\n    slog.Error(\"feishu: audio content marshal failed\", \"fileKey\", fileKey, \"err\", err)\n    return fmt.Errorf(\"send audio: %w\", err)\n}","preventionTips":["Validate fileKey before constructing MessageAudio","Pin working lark SDK versions","Avoid forked/patched SDK code","Test audio send after every SDK upgrade"],"tags":["feishu","audio","serialization","sdk"],"backgroundTag":"json-marshal-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"}