sipeed/picoclaw · error · ErrTemporary
feishu text api error (code=%d msg=%s): %w
Error message
feishu text api error (code=%d msg=%s): %w
What it means
Feishu API returned a non-zero business code for the plain-text fallback send (used after the card send failed). Unlike the card path at line 1092, this branch does NOT call invalidateTokenOnAuthError, so a stale-token failure (99991663) on the text fallback keeps failing until the token naturally expires (~2 hours). The error still wraps channels.ErrTemporary, so it is retried with backoff.
Source
Thrown at pkg/channels/feishu/feishu_64.go:1124
func (c *FeishuChannel) sendText(ctx context.Context, chatID, text string) (string, error) {
content, _ := json.Marshal(map[string]string{"text": text})
req := larkim.NewCreateMessageReqBuilder().
ReceiveIdType(larkim.CreateMessageV1ReceiveIDTypeChatId).
Body(larkim.NewCreateMessageReqBodyBuilder().
ReceiveId(chatID).
MsgType(larkim.MsgTypeText).
Content(string(content)).
Build()).
Build()
resp, err := c.client.Im.V1.Message.Create(ctx, req)
if err != nil {
return "", fmt.Errorf("feishu send text: %w", channels.ErrTemporary)
}
if !resp.Success() {
return "", fmt.Errorf("feishu text api error (code=%d msg=%s): %w", resp.Code, resp.Msg, channels.ErrTemporary)
}
logger.DebugCF("feishu", "Feishu text message sent (fallback)", map[string]any{
"chat_id": chatID,
})
if resp.Data != nil && resp.Data.MessageId != nil {
return *resp.Data.MessageId, nil
}
return "", nil
}
// sendImage uploads an image and sends it as a message.
func (c *FeishuChannel) sendImage(ctx context.Context, chatID string, file *os.File) error {
// Upload image to get image_key
uploadReq := larkim.NewCreateImageReqBuilder().
Body(larkim.NewCreateImageReqBodyBuilder().
ImageType("message").View on GitHub (pinned to 49183d7e8d)
Solutions
- Parse code=%d from the message: 99991663 -> fix/refresh app credentials; 230026 -> reword the message content; 99991400 -> slow down sends.
- Restore parity with the other paths: add c.invalidateTokenOnAuthError(resp.Code) before this return so a 99991663 self-heals on the next retry.
- Confirm receive_id is a chat_id (oc_...) and the bot is still in that chat.
Example fix
// before (feishu_64.go:1124) — no token invalidation, stale 99991663 never self-heals
if !resp.Success() {
return "", fmt.Errorf("feishu text api error (code=%d msg=%s): %w", resp.Code, resp.Msg, channels.ErrTemporary)
}
// after — same recovery as the card path at line 1091
if !resp.Success() {
c.invalidateTokenOnAuthError(resp.Code)
return "", fmt.Errorf("feishu text api error (code=%d msg=%s): %w", resp.Code, resp.Msg, channels.ErrTemporary)
} Defensive patterns
Strategy: retry
Validate before calling
if strings.TrimSpace(msg.Content) == "" {
return nil // nothing to send as text fallback
}
if msg.ChatID == "" || !strings.HasPrefix(msg.ChatID, "oc_") {
return fmt.Errorf("invalid feishu chat_id %q", msg.ChatID)
} Type guard
func isTemporarySendErr(err error) bool {
return errors.Is(err, channels.ErrTemporary)
} Try / catch
if _, err := ch.Send(ctx, msg); err != nil {
if errors.Is(err, channels.ErrTemporary) && strings.Contains(err.Error(), "code=99991663") {
// stale token: this path does NOT auto-invalidate; fix credentials or restart channel to refresh cache
}
} Prevention
- Rotate credentials during low-traffic windows so the cached token expires fast
- Avoid content that trips Feishu content filters (230026) in fallback text
- Patch parity: add invalidateTokenOnAuthError to this branch
- Keep the bot in the chat so both card and text paths work
When it happens
Trigger: Card send fails, text fallback's Message.Create returns non-success: 99991663 stale tenant_access_token (not auto-invalidated on this path), 230026 content risk / blocked text, 99991400 rate limit, or invalid receive_id.
Common situations: Message content trips Feishu's content filter so both card and text fail; credentials rotated while the old token is still cached; replying to a chat the bot just left.
Related errors
- feishu image send api error (code=%d msg=%s)
- feishu file send api error (code=%d msg=%s)
- feishu api error (code=%d msg=%s): %w
- feishu image upload api error (code=%d msg=%s)
- feishu image send: %w
AI-assisted analysis of sipeed/picoclaw@49183d7e8d (2026-08-15).
Data as JSON: /api/errors/756443478a54cb7f.
Report an issue: GitHub.