sipeed/picoclaw · error
feishu delete api error (code=%d msg=%s)
Error message
feishu delete api error (code=%d msg=%s)
What it means
FeishuChannel.deleteMessageAPI's Delete call parsed successfully but resp.Success() is false: Feishu returned a non-zero business code. Frequent codes: 230002 (bot lacks permission or is not in the chat) and invalid/nonexistent message_id (often because the message was already deleted, making this effectively idempotent-success). invalidateTokenOnAuthError(resp.Code) already ran for auth codes.
Source
Thrown at pkg/channels/feishu/feishu_64.go:288
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
}
text := c.bc.Placeholder.GetRandomText()
cardContent, err := buildMarkdownCard(text)
if err != nil {View on GitHub (pinned to 49183d7e8d)
Solutions
- Check the returned code: treat 'message not found' as success - the goal state (message gone) is achieved
- 230002: re-add the bot to the chat or grant im:message:delete scope in Feishu Open Platform
- Auth codes: token invalidation already fired; verify app credentials if it persists
- Deduplicate delete calls so retries do not re-delete
Example fix
// before
if err := ch.DeleteMessage(ctx, chatID, msgID); err != nil {
return err // 'already deleted' surfaces as a failure
}
// after
err := ch.DeleteMessage(ctx, chatID, msgID)
if err != nil && strings.Contains(err.Error(), "feishu delete api error") {
logger.Info("delete skipped", "msg_id", msgID, "err", err) // treat as done
return nil
}
return err Defensive patterns
Strategy: try-catch
Validate before calling
null
Type guard
var deleteCodeRe = regexp.MustCompile(`delete api error \(code=(\d+) msg=([^)]*)\)`)
func deleteFailureClass(err error) (code int, msg string, apiErr bool) {
m := deleteCodeRe.FindStringSubmatch(err.Error())
if m == nil { return 0, "", false }
n, _ := strconv.Atoi(m[1])
return n, m[2], true
} Try / catch
err := ch.DeleteMessage(ctx, chatID, msgID)
if code, msg, apiErr := deleteFailureClass(err); apiErr {
switch {
case code == 99991661 || code == 99991663: // auth: token refresh then retry once
case code == 230002 || strings.Contains(msg, "not found"): // already gone / no perm
return nil // goal state achieved or unreachable: accept
}
}
return err Prevention
- Treat 'message not found' delete failures as success (idempotency)
- Audit im:message:delete scope when wiring a new bot
- Do not alert page on delete business errors - they are almost always benign
- Keep auth-code handling centralized since invalidateTokenOnAuthError already fires
When it happens
Trigger: Deleting a message that no longer exists (already deleted), deleting in a chat the bot left, missing im:message:delete scope, or an expired token (99991661/99991663).
Common situations: Placeholder already removed by an earlier retry (duplicate delete); user deleted the message first; bot permissions trimmed after initial setup; deleting across tenants with mismatched app credentials.
Related errors
- feishu edit api error (code=%d msg=%s)
- feishu delete: %w
- feishu edit: %w
- feishu react: %w
- feishu react api error (code=%d msg=%s)
AI-assisted analysis of sipeed/picoclaw@49183d7e8d (2026-08-15).
Data as JSON: /api/errors/5d23229103a82e12.
Report an issue: GitHub.