chenhg5/cc-connect · warning
dingtalk: emotion returned success=false
Error message
dingtalk: emotion returned success=false
What it means
This error is returned by sendEmotion when DingTalk's emotion API returns HTTP 200 but the JSON body contains success=false, meaning DingTalk accepted the request at the transport layer but refused/refused-to-apply the emotion business operation. DingTalk reports some business failures (e.g. target message no longer exists, robot cannot reply to that message) inside a 200 envelope rather than an HTTP error status, so the library inspects the success field explicitly.
Source
Thrown at platform/dingtalk/dingtalk.go:976
resp, err := p.httpClient.Do(req)
if err != nil {
return fmt.Errorf("dingtalk: emotion request: %w", err)
}
defer func() { _ = resp.Body.Close() }()
respBody, _ := io.ReadAll(resp.Body)
if resp.StatusCode != http.StatusOK {
return fmt.Errorf("dingtalk: emotion returned status %d: %s", resp.StatusCode, string(respBody))
}
if len(respBody) == 0 {
return nil
}
var result struct {
Success *bool `json:"success"`
}
if err := json.Unmarshal(respBody, &result); err == nil && result.Success != nil && !*result.Success {
return fmt.Errorf("dingtalk: emotion returned success=false")
}
return nil
}
// StartTyping adds a DingTalk emotion to the user's message while the agent is processing.
func (p *Platform) StartTyping(ctx context.Context, rctx any) (stop func()) {
rc, ok := rctx.(replyContext)
if !ok || p.reactionEmoji == "" || rc.messageID == "" || rc.conversationId == "" {
return func() {}
}
if err := p.sendEmotion(ctx, rc, p.reactionEmoji, false); err != nil {
slog.Debug("dingtalk: add typing emotion failed", "error", err)
}
return func() {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
if err := p.sendEmotion(ctx, rc, p.reactionEmoji, true); err != nil {
slog.Debug("dingtalk: recall typing emotion failed", "error", err)View on GitHub (pinned to 4000b2338a)
Solutions
- Treat as non-fatal if it's the typing indicator (StartTyping) — it is cosmetic and safe to ignore
- Verify the robot app has emotion reply enabled for your org/conversation type in the DingTalk console
- Check whether the target messageId still exists; don't react to withdrawn/expired messages
- Capture the full response body (enable debug logging) to see any accompanying errcode
- Update the DingTalk app/robot to the latest version if emotion features were recently added
Example fix
// before: unconditionally reacting to every inbound message
p.AddDoneReaction(ctx, msg)
// after: skip if the message was withdrawn or is too old
if msg.Withdrawn || time.Since(msg.Timestamp) > maxEmotionAge { return nil }
return p.AddDoneReaction(ctx, msg) Defensive patterns
Strategy: fallback
Validate before calling
// Go: skip reaction if the target message is gone or too old
if msg.Withdrawn || time.Since(msg.Timestamp) > 10*time.Minute {
return nil
} Try / catch
if err := p.AddDoneReaction(ctx, msg); err != nil {
if strings.Contains(err.Error(), "success=false") {
// business refusal, not a bug — degrade gracefully
slog.Debug("dingtalk emotion not applied", "msg", msg.ID)
return nil
}
return err
} Prevention
- Don't react to messages older than the platform's retention window
- Check message withdrawal state before reacting
- Enable emotion reply for the robot app at the org level
- Treat typing/reaction failures as cosmetic — never propagate them to the chat flow
When it happens
Trigger: POST to /v1.0/robot/emotion/reply or /robot/emotion/recall returns 200 with {"success":false} — typically the target message is too old or deleted, the robot lacks emotion-reply rights for that conversation, or the recall targeted an emotion that no longer exists.
Common situations: AddDoneReaction fired after the user's message was withdrawn; StartTyping racing message deletion; robot app not upgraded to support emotion reply in that org; DingTalk quirk returning success=false for unsupported conversation types.
Related errors
- get access token: %w
- create AI card: status=%d, body=%s
- AI card delivery failed: %s
- stream AI card: status=%d, body=%s
- get download URL: %w
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/9a78d7edd63e0d80.
Report an issue: GitHub.