sipeed/picoclaw · error

feishu delete: %w

Error message

feishu delete: %w

What it means

FeishuChannel.deleteMessageAPI called lark SDK Im.V1.Message.Delete and the SDK returned a transport-level error before a business response could be parsed. The SDK error is wrapped with the 'feishu delete:' prefix; there is no Feishu code to inspect.

Source

Thrown at pkg/channels/feishu/feishu_64.go:284

}

// DeleteMessage implements channels.MessageDeleter.
func (c *FeishuChannel) DeleteMessage(ctx context.Context, chatID, messageID string) error {
	deleteFn := c.deleteMessageFn
	if deleteFn == nil {
		deleteFn = c.deleteMessageAPI
	}
	return deleteFn(ctx, chatID, messageID)
}

func (c *FeishuChannel) deleteMessageAPI(ctx context.Context, chatID, messageID string) error {
	req := larkim.NewDeleteMessageReqBuilder().
		MessageId(messageID).
		Build()

	resp, err := c.client.Im.V1.Message.Delete(ctx, req)
	if err != nil {
		return fmt.Errorf("feishu delete: %w", err)
	}
	if !resp.Success() {
		c.invalidateTokenOnAuthError(resp.Code)
		return fmt.Errorf("feishu delete api error (code=%d msg=%s)", resp.Code, resp.Msg)
	}
	return nil
}

// SendPlaceholder implements channels.PlaceholderCapable.
// Sends an interactive card with placeholder text and returns its message ID.
func (c *FeishuChannel) SendPlaceholder(ctx context.Context, chatID string) (string, error) {
	if !c.bc.Placeholder.Enabled {
		logger.DebugCF("feishu", "Placeholder disabled, skipping", map[string]any{
			"chat_id": chatID,
		})
		return "", nil
	}

View on GitHub (pinned to 49183d7e8d)

Solutions

  1. Retry the delete with backoff - placeholders cleanup is time-tolerant
  2. If retries keep failing, check connectivity to open.feishu.cn and proxy config
  3. Treat leftover undeleted placeholders as cosmetic: log and move on rather than blocking the pipeline

Example fix

// before
_ = ch.DeleteMessage(ctx, chatID, msgID) // one-shot, silent loss

// after
var err error
for i := 0; i < 3; i++ {
	if err = ch.DeleteMessage(ctx, chatID, msgID); err == nil {
		break
	}
	time.Sleep(time.Duration(i+1) * 300 * time.Millisecond)
}
if err != nil {
	logger.Warn("placeholder cleanup failed", "msg_id", msgID, "err", err)
}
Defensive patterns

Strategy: retry

Validate before calling

null

Type guard

func isDeleteTransportError(err error) bool {
	return err != nil && strings.HasPrefix(err.Error(), "feishu delete: ") && !strings.Contains(err.Error(), "feishu delete api error")
}

Try / catch

err := ch.DeleteMessage(ctx, chatID, msgID)
for i := 0; isDeleteTransportError(err) && i < 3; i++ {
	time.Sleep(time.Duration(i+1) * 300 * time.Millisecond)
	err = ch.DeleteMessage(ctx, chatID, msgID)
}
if err != nil { logger.Warn("placeholder cleanup failed", "msg_id", msgID, "err", err) }

Prevention

When it happens

Trigger: DELETE /open-apis/im/v1/messages/:message_id fails at the network layer: timeout, connection refused/reset, DNS failure, or an unparseable HTTP response.

Common situations: Transient connectivity loss when cleaning up placeholder messages; proxy/TLS issues in the deployment network; Feishu edge briefly unavailable; deletion burst hitting socket limits.

Related errors


AI-assisted analysis of sipeed/picoclaw@49183d7e8d (2026-08-15). Data as JSON: /api/errors/2f7e7f78deff1feb. Report an issue: GitHub.