chenhg5/cc-connect · error

%s: delete preview message: %w

Error message

%s: delete preview message: %w

What it means

This wraps an error returned by the Feishu Open Platform SDK call client.Im.Message.Delete when deleting a preview message. The %w-wrapped cause is the underlying transport/SDK error (network failure, timeout, auth issue). It is retried first via withTransientRetry and withFreshTenantAccessTokenRetry, so if you see it, the delete failed even after retries with a fresh token.

Source

Thrown at platform/feishu/feishu.go:5451

// separate final message without leaving a stale interactive card behind.
func (p *Platform) DeletePreviewMessage(ctx context.Context, previewHandle any) error {
	if !p.useInteractiveCard {
		return core.ErrNotSupported
	}

	h, ok := previewHandle.(*feishuPreviewHandle)
	if !ok {
		return fmt.Errorf("%s: invalid preview handle type %T", p.tag(), previewHandle)
	}

	req := larkim.NewDeleteMessageReqBuilder().
		MessageId(h.messageID).
		Build()
	return p.withTransientRetry(ctx, "delete preview message", func() error {
		return p.withFreshTenantAccessTokenRetry(ctx, "delete preview message", func(client *lark.Client, options ...larkcore.RequestOptionFunc) error {
			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)
	}

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Inspect the wrapped cause (%w) with errors.Unwrap/As to see if it is network, auth, or cancellation
  2. Verify app_id/app_secret are valid and the token endpoint is reachable
  3. Retry the delete manually once connectivity is restored; the message_id remains valid until deleted
  4. Check ctx cancellation sources if errors.Is(err, context.Canceled)

Example fix

if err := p.DeletePreview(ctx, h); err != nil {
    var netErr net.Error
    if errors.As(err, &netErr) { slog.Warn("feishu preview delete network issue", "err", err) }
}
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-check connectivity
if err := ctx.Err(); err != nil { return err }

Try / catch

if err := p.DeletePreview(ctx, h); err != nil {
    var cause error
    errors.As(err, &cause)
    if errors.Is(err, context.DeadlineExceeded) || isNetErr(cause) { /* schedule retry */ }
    slog.Error("feishu preview delete failed", "err", err)
}

Prevention

When it happens

Trigger: client.Im.Message.Delete returns a non-nil error after transient-retry and fresh-token retries are exhausted: network outage, expired/invalid tenant_access_token, request cancelled via ctx, or SDK-level request build failure for MessageId h.messageID.

Common situations: Network partition or proxy issues in the deployment environment; app credentials rotated or token service down; context cancelled because the user session closed before the preview delete fired.

Understand the failure class

Background: "API request failed": what wrapped HTTP errors from external APIs mean and how to find the real cause — this error's family across 29 libraries.

Related errors


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