chenhg5/cc-connect · error

%s: SendAudio: invalid reply context type %T

Error message

%s: SendAudio: invalid reply context type %T

What it means

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.

Source

Thrown at platform/feishu/feishu.go:5467

			resp, err := client.Im.Message.Delete(ctx, req, options...)
			if err != nil {
				return fmt.Errorf("%s: delete preview message: %w", p.tag(), err)
			}
			if !resp.Success() {
				return fmt.Errorf("%s: delete preview message code=%d msg=%s", p.tag(), resp.Code, resp.Msg)
			}
			return nil
		})
	})
}

// SendAudio uploads audio bytes to Feishu and sends a voice message.
// Implements core.AudioSender interface.
// Feishu audio messages require opus format; non-opus input is converted via ffmpeg.
func (p *Platform) SendAudio(ctx context.Context, rctx any, audio []byte, format string) error {
	rc, ok := rctx.(replyContext)
	if !ok {
		return fmt.Errorf("%s: SendAudio: invalid reply context type %T", p.tag(), rctx)
	}

	if format != "opus" {
		converted, err := core.ConvertAudioToOpus(ctx, audio, format)
		if err != nil {
			return fmt.Errorf("%s: convert to opus: %w", p.tag(), err)
		}
		audio = converted
		format = "opus"
	}

	var uploadResp *larkim.CreateFileResp
	if err := p.withTransientRetry(ctx, "upload audio", func() error {
		return p.withFreshTenantAccessTokenRetry(ctx, "upload audio", func(client *lark.Client, options ...larkcore.RequestOptionFunc) error {
			req := larkim.NewCreateFileReqBuilder().
				Body(larkim.NewCreateFileReqBodyBuilder().
					FileType(larkim.FileTypeOpus).
					FileName("tts_audio.opus").

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Pass the reply context exactly as obtained from this platform's incoming-message/reply API
  2. Verify only one version of the feishu platform package is linked (go version -m)
  3. Do not fabricate reply contexts; route audio through the engine's reply pipeline
  4. If you must hold contexts generically, key them by platform name

Example fix

// before
feishuPlatform.SendAudio(ctx, genericReplyCtx, audio, "mp3")
// after
if rc, ok := genericReplyCtx.(feishu.ReplyContext); ok {
    feishuPlatform.SendAudio(ctx, rc, audio, "mp3")
}
Defensive patterns

Strategy: type-guard

Validate before calling

if _, ok := rctx.(feishu.ReplyContext); !ok { return fmt.Errorf("SendAudio requires a feishu reply context, got %T", rctx) }

Type guard

func asFeishuReplyContext(v any) (feishu.ReplyContext, bool) { rc, ok := v.(feishu.ReplyContext); return rc, ok }

Prevention

When it happens

Trigger: 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).

Common situations: 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).

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06). Data as JSON: /api/errors/e2d9390086854ce6. Report an issue: GitHub.