{"record":{"id":"0d154099c75143c5","repo":"chenhg5/cc-connect","slug":"s-delete-preview-message-w","errorCode":null,"errorMessage":"%s: delete preview message: %w","messagePattern":"(.+?): delete preview message: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"platform/feishu/feishu.go","lineNumber":5451,"sourceCode":"// separate final message without leaving a stale interactive card behind.\nfunc (p *Platform) DeletePreviewMessage(ctx context.Context, previewHandle any) error {\n\tif !p.useInteractiveCard {\n\t\treturn core.ErrNotSupported\n\t}\n\n\th, ok := previewHandle.(*feishuPreviewHandle)\n\tif !ok {\n\t\treturn fmt.Errorf(\"%s: invalid preview handle type %T\", p.tag(), previewHandle)\n\t}\n\n\treq := larkim.NewDeleteMessageReqBuilder().\n\t\tMessageId(h.messageID).\n\t\tBuild()\n\treturn p.withTransientRetry(ctx, \"delete preview message\", func() error {\n\t\treturn p.withFreshTenantAccessTokenRetry(ctx, \"delete preview message\", func(client *lark.Client, options ...larkcore.RequestOptionFunc) error {\n\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","sourceCodeStart":5433,"sourceCodeEnd":5469,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/platform/feishu/feishu.go#L5433-L5469","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Inspect the wrapped cause (%w) with errors.Unwrap/As to see if it is network, auth, or cancellation","Verify app_id/app_secret are valid and the token endpoint is reachable","Retry the delete manually once connectivity is restored; the message_id remains valid until deleted","Check ctx cancellation sources if errors.Is(err, context.Canceled)"],"exampleFix":"if err := p.DeletePreview(ctx, h); err != nil {\n    var netErr net.Error\n    if errors.As(err, &netErr) { slog.Warn(\"feishu preview delete network issue\", \"err\", err) }\n}","handlingStrategy":"try-catch","validationCode":"// pre-check connectivity\nif err := ctx.Err(); err != nil { return err }","typeGuard":null,"tryCatchPattern":"if err := p.DeletePreview(ctx, h); err != nil {\n    var cause error\n    errors.As(err, &cause)\n    if errors.Is(err, context.DeadlineExceeded) || isNetErr(cause) { /* schedule retry */ }\n    slog.Error(\"feishu preview delete failed\", \"err\", err)\n}","preventionTips":["Monitor network to open.feishu.cn","Keep app credentials valid","Set generous but bounded timeouts","Log the unwrapped cause, not just the wrapper"],"tags":["feishu","api-request","network","deletion"],"backgroundTag":"api-request-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"}