{"record":{"id":"a549ebcdf7b9475e","repo":"chenhg5/cc-connect","slug":"dingtalk-get-access-token-for-emotion-w","errorCode":null,"errorMessage":"dingtalk: get access token for emotion: %w","messagePattern":"dingtalk: get access token for emotion: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"platform/dingtalk/dingtalk.go","lineNumber":927,"sourceCode":"\tRobotCode          string              `json:\"robotCode\"`\n\tOpenMsgID          string              `json:\"openMsgId\"`\n\tOpenConversationID string              `json:\"openConversationId\"`\n\tEmotionType        int                 `json:\"emotionType\"`\n\tEmotionName        string              `json:\"emotionName\"`\n\tTextEmotion        dingtalkTextEmotion `json:\"textEmotion\"`\n}\n\nfunc (p *Platform) sendEmotion(ctx context.Context, rc replyContext, emoji string, recall bool) error {\n\temoji = strings.TrimSpace(emoji)\n\tif emoji == \"\" || rc.messageID == \"\" || rc.conversationId == \"\" {\n\t\treturn nil\n\t}\n\tif p.httpClient == nil {\n\t\tp.httpClient = &http.Client{Timeout: 30 * time.Second}\n\t}\n\ttoken, err := p.getAccessToken()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"dingtalk: get access token for emotion: %w\", err)\n\t}\n\n\tpath := \"/v1.0/robot/emotion/reply\"\n\tif recall {\n\t\tpath = \"/v1.0/robot/emotion/recall\"\n\t}\n\trequestBody := dingtalkEmotionRequest{\n\t\tRobotCode:          p.robotCode,\n\t\tOpenMsgID:          rc.messageID,\n\t\tOpenConversationID: rc.conversationId,\n\t\tEmotionType:        2,\n\t\tEmotionName:        emoji,\n\t\tTextEmotion: dingtalkTextEmotion{\n\t\t\tEmotionID:    customTextEmotionID,\n\t\t\tEmotionName:  emoji,\n\t\t\tText:         emoji,\n\t\t\tBackgroundID: customTextEmotionBackground,\n\t\t},","sourceCodeStart":909,"sourceCodeEnd":945,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/platform/dingtalk/dingtalk.go#L909-L945","documentation":"This error is returned by Platform.sendEmotion when the call to p.getAccessToken() fails while trying to send an emotion (typing indicator, done reaction, recall) through the DingTalk robot emotion API. The DingTalk emotion endpoints require a fresh access token, obtained by exchanging the configured appKey/appSecret with DingTalk's token endpoint; this error wraps whatever went wrong during that exchange (network failure, invalid credentials, or a non-success response from the token API). It means the emotion could not even be attempted because no valid token was available.","triggerScenarios":"Calling StartTyping, AddDoneReaction, or sendEmotion (reply/recall) when getAccessToken() fails — e.g. DingTalk token endpoint unreachable, p.appKey/p.appSecret empty or wrong, token response missing accessToken, or the cached token expired and refresh failed.","commonSituations":"Missing or mistyped appKey/appSecret in config.toml; DingTalk app disabled or key rotated; corporate firewall/DNS blocking oapi.dingtalk.com; rate limiting or outage on the token endpoint.","solutions":["Verify appKey and appSecret are set and correct in the DingTalk platform config","Test network reachability to DingTalk's token endpoint from the host (curl the token URL)","Check the DingTalk developer console to confirm the app is enabled and credentials are current","Retry; if intermittent, check for rate limits or transient network issues"],"exampleFix":"// before (config)\n[platforms.dingtalk]\nappKey = \"\"\nappSecret = \"forgot\"\n// after\n[platforms.dingtalk]\nappKey = \"ding0123456789abcdef\"\nappSecret = \"real-secret-from-dingtalk-console\"","handlingStrategy":"try-catch","validationCode":"// Go: verify credentials exist before attempting emotion send\nif p.appKey == \"\" || p.appSecret == \"\" {\n    return errors.New(\"dingtalk: appKey/appSecret not configured\")\n}","typeGuard":null,"tryCatchPattern":"if err := p.StartTyping(ctx, rctx); err != nil {\n    var tokErr *url.Error\n    if errors.As(err, &tokErr) {\n        slog.Warn(\"dingtalk token fetch network failure\", \"err\", err)\n    } else {\n        slog.Error(\"dingtalk emotion token error\", \"err\", err)\n    }\n}","preventionTips":["Set appKey/appSecret in config and validate at startup with a doctor/health check","Monitor token-fetch failures; alert on repeated occurrences","Keep credentials in a secret store, not inline config, and rotate on schedule"],"tags":["dingtalk","authentication","network","access-token"],"backgroundTag":"oauth-token-exchange-failed","analyzedSha":"4000b2338aa6e850c99df54f8b0ed6ed7460b401","analyzedAt":"2026-09-06T11:45:09.575Z","contentChangedAt":"2026-09-06T11:45:09.575Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}