{"record":{"id":"e2d9390086854ce6","repo":"chenhg5/cc-connect","slug":"s-sendaudio-invalid-reply-context-type-t","errorCode":null,"errorMessage":"%s: SendAudio: invalid reply context type %T","messagePattern":"(.+?): SendAudio: invalid reply context type %T","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"platform/feishu/feishu.go","lineNumber":5467,"sourceCode":"\t\t\tresp, err := client.Im.Message.Delete(ctx, req, options...)\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"%s: delete preview message: %w\", p.tag(), err)\n\t\t\t}\n\t\t\tif !resp.Success() {\n\t\t\t\treturn fmt.Errorf(\"%s: delete preview message code=%d msg=%s\", p.tag(), resp.Code, resp.Msg)\n\t\t\t}\n\t\t\treturn nil\n\t\t})\n\t})\n}\n\n// SendAudio uploads audio bytes to Feishu and sends a voice message.\n// Implements core.AudioSender interface.\n// Feishu audio messages require opus format; non-opus input is converted via ffmpeg.\nfunc (p *Platform) SendAudio(ctx context.Context, rctx any, audio []byte, format string) error {\n\trc, ok := rctx.(replyContext)\n\tif !ok {\n\t\treturn fmt.Errorf(\"%s: SendAudio: invalid reply context type %T\", p.tag(), rctx)\n\t}\n\n\tif format != \"opus\" {\n\t\tconverted, err := core.ConvertAudioToOpus(ctx, audio, format)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"%s: convert to opus: %w\", p.tag(), err)\n\t\t}\n\t\taudio = converted\n\t\tformat = \"opus\"\n\t}\n\n\tvar uploadResp *larkim.CreateFileResp\n\tif err := p.withTransientRetry(ctx, \"upload audio\", func() error {\n\t\treturn p.withFreshTenantAccessTokenRetry(ctx, \"upload audio\", func(client *lark.Client, options ...larkcore.RequestOptionFunc) error {\n\t\t\treq := larkim.NewCreateFileReqBuilder().\n\t\t\t\tBody(larkim.NewCreateFileReqBodyBuilder().\n\t\t\t\t\tFileType(larkim.FileTypeOpus).\n\t\t\t\t\tFileName(\"tts_audio.opus\").","sourceCodeStart":5449,"sourceCodeEnd":5485,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/platform/feishu/feishu.go#L5449-L5485","documentation":"SendAudio implements the core.AudioSender interface and expects the reply-context parameter rctx to be the platform-internal replyContext type. This error is thrown when the type assertion rctx.(replyContext) fails, i.e. the caller passed a reply context produced by a different platform or an unexpected value. Like error 1230, it indicates a caller/platform contract violation rather than a runtime condition.","triggerScenarios":"Calling SendAudio with an rctx from another platform adapter, a raw chat/message ID, a nil interface, or a handle from a differently-built feishu package (duplicate module versions).","commonSituations":"Engine/plugin code that caches reply contexts across platforms; a custom agent sending audio through the wrong platform instance; mixing two versions of the feishu package in one binary (vendored vs module).","solutions":["Pass the reply context exactly as obtained from this platform's incoming-message/reply API","Verify only one version of the feishu platform package is linked (go version -m)","Do not fabricate reply contexts; route audio through the engine's reply pipeline","If you must hold contexts generically, key them by platform name"],"exampleFix":"// before\nfeishuPlatform.SendAudio(ctx, genericReplyCtx, audio, \"mp3\")\n// after\nif rc, ok := genericReplyCtx.(feishu.ReplyContext); ok {\n    feishuPlatform.SendAudio(ctx, rc, audio, \"mp3\")\n}","handlingStrategy":"type-guard","validationCode":"if _, ok := rctx.(feishu.ReplyContext); !ok { return fmt.Errorf(\"SendAudio requires a feishu reply context, got %T\", rctx) }","typeGuard":"func asFeishuReplyContext(v any) (feishu.ReplyContext, bool) { rc, ok := v.(feishu.ReplyContext); return rc, ok }","tryCatchPattern":null,"preventionTips":["Always pass the reply context straight from the incoming message handler","Verify single feishu package version in the binary","Never fabricate reply contexts; use the engine reply pipeline"],"tags":["feishu","type-assertion","audio","reply-context"],"backgroundTag":"type-mismatch","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"}