{"record":{"id":"17e1308a8a7f5865","repo":"chenhg5/cc-connect","slug":"s-chatid-is-empty","errorCode":null,"errorMessage":"%s: chatID is empty","messagePattern":"(.+?): chatID is empty","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"platform/feishu/feishu.go","lineNumber":5067,"sourceCode":"//     → returns message_id; both ids are stored on feishuPreviewHandle.\n//\n// If step (1) fails OR we're in thread/reply mode (Reply API doesn't accept\n// card_id reference), we fall back to the inline-card-JSON path. The handle's\n// cardID stays empty in that case and the engine routes EventText through the\n// full-card Patch path (= original #657 behavior, no typewriter).\nfunc (p *Platform) SendPreviewStart(ctx context.Context, rctx any, content string) (any, error) {\n\tif !p.useInteractiveCard {\n\t\treturn nil, core.ErrNotSupported\n\t}\n\n\trc, ok := rctx.(replyContext)\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"%s: invalid reply context type %T\", p.tag(), rctx)\n\t}\n\n\tchatID := rc.chatID\n\tif chatID == \"\" {\n\t\treturn nil, fmt.Errorf(\"%s: chatID is empty\", p.tag())\n\t}\n\n\t// Card 2.0 path: engine passes a pre-built rich card JSON; pass it through.\n\tvar cardJSON string\n\tvar sendContent string // what goes into the Im.Message.Create / Reply content field\n\tvar cardID string      // cardkit-v1 entity id (empty = no streaming text path)\n\tif isCardJSON(content) {\n\t\tcardJSON = content\n\t\t// Try cardkit-v1 two-step flow regardless of Reply vs Create. Both\n\t\t// Im.Message.Reply and Im.Message.Create accept the {type:card,data:{card_id}}\n\t\t// content schema (verified by direct API call); skipping Reply mode would\n\t\t// disable cardkit-v1 streaming on every @-mention turn (the dominant case).\n\t\tif id, err := p.createCardEntity(ctx, cardJSON); err == nil {\n\t\t\tcardID = id\n\t\t\tsendContent = fmt.Sprintf(`{\"type\":\"card\",\"data\":{\"card_id\":\"%s\"}}`, id)\n\t\t} else {\n\t\t\tslog.Info(p.tag()+\": create card entity failed, falling back to inline card JSON\",\n\t\t\t\t\"error\", err)","sourceCodeStart":5049,"sourceCodeEnd":5085,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/platform/feishu/feishu.go#L5049-L5085","documentation":"SendPreviewStart found the reply context's chatID field empty after the type guard passed. Guard preventing a card preview send to an unresolved target; the caller must supply a reply context carrying a chat id.","triggerScenarios":"Thrown at platform/feishu/feishu.go:5067 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Ensure the message originated from a real chat event","Reconstruct the reply context from a valid session key"],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"4000b2338aa6e850c99df54f8b0ed6ed7460b401","analyzedAt":"2026-09-06T11:45:09.575Z","contentChangedAt":"2026-09-06T11:45:09.575Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}