chenhg5/cc-connect · error
weixin: sendMessage: nil request
Error message
weixin: sendMessage: nil request
What it means
sendMessage is the low-level API call that posts an outbound message to WeChat. It validates its argument first and rejects a nil *sendMessageReq to avoid a nil-pointer panic during json.Marshal. This is a programmer error passed up by callers like sendText/sendSingleItem.
Source
Thrown at platform/weixin/client.go:164
if errors.Is(err, context.DeadlineExceeded) {
return &getUpdatesResp{Ret: 0, Msgs: nil, GetUpdatesBuf: buf}, nil
}
var ne net.Error
if errors.As(err, &ne) && ne.Timeout() {
return &getUpdatesResp{Ret: 0, Msgs: nil, GetUpdatesBuf: buf}, nil
}
return nil, err
}
var out getUpdatesResp
if err := json.Unmarshal(raw, &out); err != nil {
return nil, fmt.Errorf("weixin: getUpdates json: %w", err)
}
return &out, nil
}
func (c *apiClient) sendMessage(ctx context.Context, msg *sendMessageReq) error {
if msg == nil {
return fmt.Errorf("weixin: sendMessage: nil request")
}
msg.BaseInfo = baseInfo{ChannelVersion: channelVersion}
payload, err := json.Marshal(msg)
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 {View on GitHub (pinned to 4000b2338a)
Solutions
- Find the caller producing nil (sendText or sendSingleItem) and ensure it always builds sendMessageReq
- Add an upstream guard returning a descriptive error when there is nothing to send
- If sendSingleItem can be a no-op, return nil early instead of forwarding a nil request
Example fix
// before
if len(items) == 0 { return fmt.Errorf("weixin: sendText: empty item_list") }
// after: also guard before calling sendMessage
if len(items) == 0 { return fmt.Errorf("weixin: sendText: empty item_list") }
msg := buildSendMessageReq(to, items, clientID)
if msg == nil { return fmt.Errorf("weixin: sendText: nil request") } Defensive patterns
Strategy: validation
Validate before calling
if msg == nil { return errors.New("weixin: sendMessage called with nil request") } Try / catch
if err := c.sendMessage(ctx, req); err != nil {
if strings.Contains(err.Error(), "nil request") { slog.Error("weixin: programmer error: nil req built upstream") }
return err
} Prevention
- Never build requests conditionally without a fallback path
- Return early (nil) in callers when there is nothing to send
- Add unit tests covering empty-item edge cases
When it happens
Trigger: A caller (sendText, sendSingleItem) constructs no request — e.g. sendSingleItem called with an empty/zero item so the req pointer is never built, or refactored code paths pass nil directly.
Common situations: Code changes that build the request conditionally and skip building it on edge cases; calling sendSingleItem with no media/text item after validation gaps upstream.
Related errors
- bind mode requires --token
- new/QR mode does not accept --token; use `cc-connect weixin
- internal: unknown mode %q
- empty qrcode_img_content from server
- 二维码多次过期,请重试 setup
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/dc17f3002931a7ce.
Report an issue: GitHub.