chenhg5/cc-connect · error
wecom-ws: chatID is empty, cannot send file
Error message
wecom-ws: chatID is empty, cannot send file
What it means
SendFile found a valid wsReplyContext but its chatID field is empty, so there is no WeCom chat to deliver the file to. The platform refuses the call rather than sending a message that the API would reject.
Source
Thrown at platform/wecom/websocket_outbound_media.go:165
case "image/jpeg", "image/jpg":
return "image.jpg"
case "image/gif":
return "image.gif"
case "image/webp":
return "image.webp"
default:
return "image.png"
}
}
// SendFile uploads and sends a file through the WeCom AI Bot WebSocket API.
func (p *WSPlatform) SendFile(ctx context.Context, rctx any, file core.FileAttachment) error {
rc, ok := rctx.(wsReplyContext)
if !ok {
return fmt.Errorf("wecom-ws: SendFile: invalid reply context type %T", rctx)
}
if rc.chatID == "" {
return fmt.Errorf("wecom-ws: chatID is empty, cannot send file")
}
if len(file.Data) == 0 {
return fmt.Errorf("wecom-ws: file data is empty")
}
mediaID, err := p.uploadWSMedia(ctx, "file", wsFileFileName(file), file.Data)
if err != nil {
return fmt.Errorf("wecom-ws: send file: %w", err)
}
if err := p.sendWSMediaMessage(ctx, rc.chatID, "file", mediaID); err != nil {
return fmt.Errorf("wecom-ws: send file: %w", err)
}
return nil
}
func wsFileFileName(file core.FileAttachment) string {
name := filepath.Base(strings.TrimSpace(file.FileName))
if name != "" && name != "." {View on GitHub (pinned to 4000b2338a)
Solutions
- Populate rc.chatID from the inbound WeCom message's chat id before calling SendFile
- Guard callers: skip or queue file sends when no chatID is known
- In scheduled/bot-initiated flows, resolve a target chatID from configuration instead of relying on reply context
Example fix
// before
var rc wsReplyContext // chatID empty
p.SendFile(ctx, rc, file)
// after
rc := wsReplyContext{chatID: inboundMsg.ChatID}
if rc.chatID == "" {
return fmt.Errorf("no target chat for file")
}
p.SendFile(ctx, rc, file) Defensive patterns
Strategy: validation
Validate before calling
if rc, ok := rctx.(wsReplyContext); !ok || rc.chatID == "" {
return fmt.Errorf("cannot send file: no wecom chat id")
} Type guard
func hasChatID(rctx any) bool {
rc, ok := rctx.(wsReplyContext)
return ok && rc.chatID != ""
} Try / catch
if err := p.SendFile(ctx, rc, file); err != nil && strings.Contains(err.Error(), "chatID is empty") {
log.Warn("skipping file send: no target chat")
} Prevention
- Always populate chatID from the inbound event before replying
- In cron/scheduled flows resolve a chatID from config instead of reply context
- Assert chatID non-empty in tests that build reply contexts
When it happens
Trigger: Called with a wsReplyContext that was constructed with an empty chatID — e.g. a zero-value wsReplyContext{}, or an inbound event that lacked chat identity.
Common situations: Reply context created programmatically in tests or cron/scheduled jobs with no inbound chat; webhook event parsed but chat_id field missing from payload; context default-initialized instead of populated from the message.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- wecom-ws: bot_id and bot_secret are required for websocket m
- wecom-ws: invalid aeskey base64 length
- empty media data
- media too large: %d chunks exceeds maximum %d
- upload init: empty upload_id
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/a297f165638a3c85.
Report an issue: GitHub.