chenhg5/cc-connect · error
%s: chatID is empty, cannot send new message
Error message
%s: chatID is empty, cannot send new message
What it means
A defensive pre-condition check in sendNewMessageToChat: the replyContext has no chatID, so a brand-new (non-reply) message cannot be addressed to any conversation. The platform tag is prefixed to make the originating adapter instance identifiable in logs.
Source
Thrown at platform/feishu/feishu.go:4031
func (p *Platform) shouldReplyInThread(rc replyContext) bool {
if rc.messageID == "" {
return false
}
return p.threadIsolation && isThreadSessionKey(rc.sessionKey)
}
// shouldUseThreadOrReplyAPI is true when we should call Im.Message.Reply (optionally with ReplyInThread).
func (p *Platform) shouldUseThreadOrReplyAPI(rc replyContext) bool {
if rc.messageID == "" {
return false
}
return !p.noReplyToTrigger
}
func (p *Platform) sendNewMessageToChat(ctx context.Context, rc replyContext, msgType, content string) error {
if rc.chatID == "" {
return fmt.Errorf("%s: chatID is empty, cannot send new message", p.tag())
}
return p.createMessage(ctx, rc.chatID, msgType, content, "send")
}
func (p *Platform) buildReplyMessageReqBody(rc replyContext, msgType, content string) *larkim.ReplyMessageReqBody {
body := larkim.NewReplyMessageReqBodyBuilder().
MsgType(msgType).
Content(content)
if p.shouldReplyInThread(rc) {
body.ReplyInThread(true)
}
return body.Build()
}
func (p *Platform) replyMessage(ctx context.Context, rc replyContext, msgType, content string) error {
req := larkim.NewReplyMessageReqBuilder().
MessageId(rc.messageID).
Body(p.buildReplyMessageReqBody(rc, msgType, content)).View on GitHub (pinned to 4000b2338a)
Solutions
- Log the raw incoming event to confirm whether chat_id is present in the payload.
- Check how replyContext is populated (event extraction) and fix the field mapping for the message type in question.
- Skip sendNewMessageToChat and fall back to reply-message mode when chatID is empty.
- Pin/upgrade the lark SDK to a version whose event schema matches the parsing code.
Example fix
// before
if rc.chatID == "" {
return fmt.Errorf("%s: chatID is empty, cannot send new message", p.tag())
}
// after
if rc.chatID == "" {
slog.Warn(p.tag()+": chatID empty, falling back to reply mode")
return p.replyMessage(ctx, rc, msgType, content)
} Defensive patterns
Strategy: validation
Validate before calling
if rc.chatID == "" {
return errors.New("cannot send: chatID is empty")
}
if err := sendNewMessageToChat(ctx, rc, msgType, content); err != nil { ... } Type guard
func canSendNewMessage(rc replyContext) bool { return rc.chatID != "" } Try / catch
if err := p.sendNewMessageToChat(ctx, rc, msgType, content); err != nil {
if strings.Contains(err.Error(), "chatID is empty") {
// fall back to reply path
return p.replyMessage(ctx, rc, msgType, content)
}
return err
} Prevention
- Assert chat_id is present when parsing every incoming Feishu event.
- Add a startup test that parses sample events for each message type.
- Log raw event payloads when chat_id extraction fails.
- Cover the chatID extraction path with a unit test per SDK version bump.
When it happens
Trigger: An event/message flow builds a replyContext from an incoming Feishu event where the chat_id (chat_id / chatId field) is absent — e.g. thread-style or special message types, or a schema change in the event payload — and then tries to send a new message instead of a threaded reply.
Common situations: Feishu SDK version upgrade renamed/moved the chat_id field in the event struct, message received through a channel type that omits chat_id, or a code path constructing replyContext manually without setting chatID.
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
- app_id/app_secret are required
- invalid remote image URL
- invalid --platform-type %q, want feishu or lark
- unknown validation error
- decode response: %w
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/70be978b92122684.
Report an issue: GitHub.