chenhg5/cc-connect · error
weixin: sendMessage: ret=%d errcode=%d errmsg=%s
Error message
weixin: sendMessage: ret=%d errcode=%d errmsg=%s
What it means
The WeChat sendMessage endpoint answered with valid JSON but a non-zero Ret, meaning the API refused the message. The code logs ret/errcode/errmsg at warn level (with content length) and returns them as an error so callers know delivery failed.
Source
Thrown at platform/weixin/client.go:186
if err != nil {
return err
}
raw, err := c.post(ctx, "ilink/bot/sendmessage", payload, 0, "sendMessage")
if err != nil {
return err
}
if len(bytes.TrimSpace(raw)) == 0 {
return nil
}
var resp sendMessageResp
if err := json.Unmarshal(raw, &resp); err != nil {
return fmt.Errorf("weixin: sendMessage: response json: %w: %s", err, truncateForLog(raw, 256))
}
if resp.Ret != 0 {
slog.Warn("weixin: sendMessage declined by API",
"ret", resp.Ret, "errcode", resp.Errcode, "errmsg", resp.Errmsg,
"content_len", len(payload))
return fmt.Errorf("weixin: sendMessage: ret=%d errcode=%d errmsg=%s",
resp.Ret, resp.Errcode, resp.Errmsg)
}
return nil
}
func (c *apiClient) getUploadURL(ctx context.Context, req getUploadURLRequest) (*getUploadURLResponse, error) {
req.BaseInfo = baseInfo{ChannelVersion: channelVersion}
payload, err := json.Marshal(req)
if err != nil {
return nil, err
}
raw, err := c.post(ctx, "ilink/bot/getuploadurl", payload, 0, "getUploadUrl")
if err != nil {
return nil, err
}
var out getUploadURLResponse
if err := json.Unmarshal(raw, &out); err != nil {
return nil, fmt.Errorf("weixin: getUploadUrl json: %w", err)View on GitHub (pinned to 4000b2338a)
Solutions
- Read the logged errcode/errmsg from the slog.Warn line to identify the API's reason
- Refresh the session/context_token (re-authenticate or getConfig) and retry
- Check content length and split or trim oversized messages before sending
- Add backoff/retry for rate-limit style errcodes and re-establish the session for auth errcodes
Defensive patterns
Strategy: retry
Try / catch
if err := sendText(...); err != nil {
var apiErr APIError
if errors.As(err, &apiErr) {
if isAuthErrcode(apiErr.Errcode) { refreshSession(); return retry() }
if isRateLimitErrcode(apiErr.Errcode) { return retryWithBackoff() }
}
return err
} Prevention
- Refresh context tokens proactively before expiry
- Split messages to stay under content-length limits
- Classify errcodes: retryable (rate limit) vs fatal (auth/ban)
When it happens
Trigger: WeChat rejects the outbound message: invalid context_token, expired ticket/session, message to a user the bot cannot reach, content policy rejection, or rate limiting — anything the API reports via ret/errcode/errmsg.
Common situations: Stale context_token after re-login of the linked account; banned or restricted bot account; sending too fast and hitting server-side rate limits; oversized message content.
Related errors
- cloud_web: send HTTP %d: %s
- weixin: sendMessage: response json: %w: %s
- weixin: getConfig ret=%d errcode=%d errmsg=%s
- weixin: context_token is required for send
- weixin: sendText: empty item_list
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/3e8e84256633ee5d.
Report an issue: GitHub.