{"record":{"id":"18ff50a3e9957f17","repo":"sipeed/picoclaw","slug":"feishu-react-api-error-code-d-msg-s","errorCode":null,"errorMessage":"feishu react api error (code=%d msg=%s)","messagePattern":"feishu react api error \\(code=(.+?) msg=(.+?)\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"pkg/channels/feishu/feishu_64.go","lineNumber":462,"sourceCode":"\n\tresp, err := c.client.Im.V1.MessageReaction.Create(ctx, req)\n\tif err != nil {\n\t\tlogger.ErrorCF(\"feishu\", \"Failed to add reaction\", map[string]any{\n\t\t\t\"emoji\":      chosenEmoji,\n\t\t\t\"message_id\": messageID,\n\t\t\t\"error\":      err.Error(),\n\t\t})\n\t\treturn func() {}, fmt.Errorf(\"feishu react: %w\", err)\n\t}\n\tif !resp.Success() {\n\t\tc.invalidateTokenOnAuthError(resp.Code)\n\t\tlogger.ErrorCF(\"feishu\", \"Reaction API error\", map[string]any{\n\t\t\t\"emoji\":      chosenEmoji,\n\t\t\t\"message_id\": messageID,\n\t\t\t\"code\":       resp.Code,\n\t\t\t\"msg\":        resp.Msg,\n\t\t})\n\t\treturn func() {}, fmt.Errorf(\"feishu react api error (code=%d msg=%s)\", resp.Code, resp.Msg)\n\t}\n\n\tvar reactionID string\n\tif resp.Data != nil && resp.Data.ReactionId != nil {\n\t\treactionID = *resp.Data.ReactionId\n\t}\n\tif reactionID == \"\" {\n\t\treturn func() {}, nil\n\t}\n\n\tvar undone atomic.Bool\n\tundo := func() {\n\t\tif !undone.CompareAndSwap(false, true) {\n\t\t\treturn\n\t\t}\n\t\tdelReq := larkim.NewDeleteMessageReactionReqBuilder().\n\t\t\tMessageId(messageID).\n\t\t\tReactionId(reactionID).","sourceCodeStart":444,"sourceCodeEnd":480,"githubUrl":"https://github.com/sipeed/picoclaw/blob/49183d7e8daed0dba89ddbb6fcb60089401d9680/pkg/channels/feishu/feishu_64.go#L444-L480","documentation":"The reaction-create call parsed but resp.Success() is false: Feishu returned a non-zero business code. Typical causes: the emoji_type is not in Feishu's allowed set, the bot lacks reaction permission in that chat, the message_id is invalid, or the auth token expired (invalidateTokenOnAuthError already ran for auth codes). The code and msg are in the error text and logged.","triggerScenarios":"MessageReaction.Create with an unsupported emoji_type string, a reaction attempted in a chat the bot cannot react in, or reacting to a deleted message.","commonSituations":"Custom emoji mappings bypassing the allow-list (Feishu expects types like 'THUMBSUP', 'DONE'); permission scopes trimmed after setup; racing a message deletion.","solutions":["Read the code/msg in the error: unsupported emoji means your emoji map needs the Feishu emoji_type key, not a unicode character","Permission codes: grant im:message.reaction:create or re-add the bot to the chat","Skip reactions on this message instead of failing - they are cosmetic","Pin the reaction map to Feishu's documented emoji list and unit-test it"],"exampleFix":"// before\nemoji := \"👍\" // unicode: Feishu rejects it\nundo, err := ch.React(ctx, chatID, msgID, emoji)\n\n// after\nemoji := \"THUMBSUP\" // Feishu emoji_type key\nundo, err := ch.React(ctx, chatID, msgID, emoji)\nif err != nil {\n\tlogger.Warn(\"reaction skipped\", \"emoji\", emoji, \"err\", err)\n\tundo = func() {}\n}","handlingStrategy":"fallback","validationCode":"// validate emoji against Feishu's documented emoji_type keys before calling\nvar allowedEmojis = map[string]bool{\"THUMBSUP\": true, \"DONE\": true, \"OK\": true /* ... */}\n\nfunc emojiAllowed(e string) bool { return allowedEmojis[e] }","typeGuard":"func isReactAPIError(err error) bool {\n\treturn err != nil && strings.Contains(err.Error(), \"feishu react api error\")\n}","tryCatchPattern":"undo, err := ch.React(ctx, chatID, msgID, emoji)\nif isReactAPIError(err) {\n\tlogger.Warn(\"reaction rejected by API; skipping\", \"emoji\", emoji, \"err\", err)\n\tundo = func(){}\nerr = nil // cosmetic feature: never fail the send on it\n}\nreturn undo, err","preventionTips":["Use only Feishu emoji_type keys (THUMBSUP, DONE...), never unicode emoji","Maintain the allow-list as data and unit-test it against the card builder","Skip reactions on messages older than a threshold (they may be deleted)","Log code+msg on reject; unsupported-emoji is by far the most common cause"],"tags":["feishu","reaction","api-error","emoji","non-fatal"],"backgroundTag":null,"analyzedSha":"49183d7e8daed0dba89ddbb6fcb60089401d9680","analyzedAt":"2026-08-15T21:55:41.315Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}