{"record":{"id":"8885bba29c72f79e","repo":"chenhg5/cc-connect","slug":"wecom-send-image-w","errorCode":null,"errorMessage":"wecom: send image: %w","messagePattern":"wecom: send image: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"platform/wecom/wecom.go","lineNumber":503,"sourceCode":"\treturn nil\n}\n\n// Send sends a new message (same as Reply for WeChat Work)\nfunc (p *Platform) Send(ctx context.Context, rctx any, content string) error {\n\treturn p.Reply(ctx, rctx, content)\n}\n\n// SendImage uploads and sends an image to the user.\n// Implements core.ImageSender.\nfunc (p *Platform) SendImage(ctx context.Context, rctx any, img core.ImageAttachment) error {\n\trc, ok := rctx.(replyContext)\n\tif !ok {\n\t\treturn fmt.Errorf(\"wecom: SendImage: invalid reply context type %T\", rctx)\n\t}\n\n\taccessToken, err := p.getAccessToken()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"wecom: send image: %w\", err)\n\t}\n\n\tmediaID, err := p.uploadImageMedia(accessToken, img)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"wecom: send image: %w\", err)\n\t}\n\n\tpayload := map[string]any{\n\t\t\"touser\":  rc.userID,\n\t\t\"msgtype\": \"image\",\n\t\t\"agentid\": p.agentID,\n\t\t\"image\":   map[string]string{\"media_id\": mediaID},\n\t}\n\n\tbody, _ := json.Marshal(payload)\n\tapiURL := p.wecomAPIURL(\"/cgi-bin/message/send\", url.Values{\n\t\t\"access_token\": []string{accessToken},\n\t})","sourceCodeStart":485,"sourceCodeEnd":521,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/platform/wecom/wecom.go#L485-L521","documentation":"After validating the reply context, SendImage() calls getAccessToken() to authenticate the message/send and media/upload API calls. Any token acquisition failure (network, bad credentials, WeCom errcode) is returned wrapped as \"wecom: send image: %w\".","triggerScenarios":"getAccessToken fails inside SendImage: invalid corp_secret (errcode 40001), unreachable API host, blocked egress, or timeout via a misconfigured proxy.","commonSituations":"Rotated corp secret not updated in config; restricted egress on the deployment host; trusted-IP allowlist in the WeCom app excluding the server.","solutions":["Fix the underlying token error (see the wrapped cause): update corp_id/corp_secret, restore network access, or correct proxy settings","Confirm the app's trusted IP allowlist includes the server's egress address","Test token acquisition independently via curl on the gettoken endpoint before retrying image sends"],"exampleFix":"// before\n\"corp_secret\": \"typo-secret\" // token fetch fails -> send image: gettoken errcode 40001\n// after\n\"corp_secret\": \"correctCurrentSecret\"","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err := p.SendImage(ctx, rctx, img); err != nil {\n\tvar netErr net.Error\n\tif errors.As(err, &netErr) && netErr.Timeout() {\n\t\t// retry with backoff\n\t}\n\treturn fmt.Errorf(\"image delivery failed: %w\", err)\n}","preventionTips":["Keep credentials current so token acquisition succeeds","Confirm egress access to the WeCom API host before deploying image features","Surface the wrapped cause rather than swallowing it, to distinguish token vs upload vs send failures"],"tags":["wecom","network","authentication","image"],"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-14T00:17:10.932Z"}