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

  1. Populate rc.chatID from the inbound WeCom message's chat id before calling SendFile
  2. Guard callers: skip or queue file sends when no chatID is known
  3. 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

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


AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06). Data as JSON: /api/errors/a297f165638a3c85. Report an issue: GitHub.