chenhg5/cc-connect · error

%s: delete preview message code=%d msg=%s

Error message

%s: delete preview message code=%d msg=%s

What it means

The Feishu API responded successfully at the HTTP layer but returned a non-success business code in the response body. The error carries the platform tag, the numeric Feishu error code, and the human-readable msg from Feishu. Unlike 1231 this is a definitive API-level rejection, not a transport failure, so retries with a fresh token have already been attempted.

Source

Thrown at platform/feishu/feishu.go:5454

		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)
	}

	if format != "opus" {
		converted, err := core.ConvertAudioToOpus(ctx, audio, format)
		if err != nil {

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Read the code=%d in the message and look it up in Feishu's error-code docs
  2. Grant the bot the im:message deletion scope and republish the app version
  3. Treat 'message already deleted' codes as benign and skip
  4. Verify the message_id belongs to a message sent by this bot

Example fix

// before: treating all failures as fatal
if err := p.DeletePreview(ctx, h); err != nil { return err }
// after
if err := p.DeletePreview(ctx, h); err != nil && !strings.Contains(err.Error(), "code=230002") { return err }
Defensive patterns

Strategy: try-catch

Validate before calling

// verify bot scopes before calling: ensure im:message / im:message:delete granted in Feishu admin console

Try / catch

if err := p.DeletePreview(ctx, h); err != nil {
    var codeErr *FeishuAPIError // parse code=N from message if needed
    if strings.Contains(err.Error(), "230002") { return nil } // already deleted: benign
    return err
}

Prevention

When it happens

Trigger: client.Im.Message.Delete succeeds over HTTP but resp.Success() is false — e.g. code 99991663/99991661 (token/permission), code 230002 (message not found, already deleted), or other im:message deletion permission errors for the bot.

Common situations: Bot lacks im:message:delete (or im:message) scope; the preview message was already deleted by a user or retention policy; the bot tries to delete a message it did not send; app credential misconfiguration in config.toml.

Related errors


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