{"record":{"id":"206c3f54bf60e973","repo":"chenhg5/cc-connect","slug":"ai-card-delivery-failed-s","errorCode":null,"errorMessage":"AI card delivery failed: %s","messagePattern":"AI card delivery failed: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"platform/dingtalk/card.go","lineNumber":198,"sourceCode":"\t}\n\n\t// Check deliverResults for actual delivery success\n\tvar deliverCheck struct {\n\t\tResult struct {\n\t\t\tDeliverResults []struct {\n\t\t\t\tSuccess  bool   `json:\"success\"`\n\t\t\t\tErrorMsg string `json:\"errorMsg\"`\n\t\t\t} `json:\"deliverResults\"`\n\t\t} `json:\"result\"`\n\t}\n\tif err := json.Unmarshal(respBody, &deliverCheck); err == nil {\n\t\tfor _, dr := range deliverCheck.Result.DeliverResults {\n\t\t\tif !dr.Success {\n\t\t\t\tslog.Warn(\"dingtalk: AI card delivery failed\",\n\t\t\t\t\t\"errorMsg\", dr.ErrorMsg,\n\t\t\t\t\t\"outTrackId\", outTrackId,\n\t\t\t\t\t\"isGroup\", isGroup)\n\t\t\t\treturn nil, fmt.Errorf(\"AI card delivery failed: %s\", dr.ErrorMsg)\n\t\t\t}\n\t\t}\n\t}\n\n\tslog.Info(\"dingtalk: AI card created\",\n\t\t\"cardInstanceId\", cardInstanceId,\n\t\t\"outTrackId\", resolvedOutTrackId)\n\n\tcard := &aiCard{\n\t\tcardInstanceId: cardInstanceId,\n\t\toutTrackId:     resolvedOutTrackId,\n\t\ttemplateKey:    p.cardTemplateKey,\n\t\tplatform:       p,\n\t\tstate:          \"processing\",\n\t\tthrottleMs:     p.cardThrottleMs,\n\t\tdone:           make(chan struct{}),\n\t}\n","sourceCodeStart":180,"sourceCodeEnd":216,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/platform/dingtalk/card.go#L180-L216","documentation":"DingTalk returned HTTP 200 but the response's deliverResults array contains an entry with success=false, meaning the card instance was created but could not actually be delivered to the conversation (platform/dingtalk/card.go:198, createAICard). The DingTalk per-delivery errorMsg is embedded in the error. Unlike transport failures, this is an application-level rejection by DingTalk's IM delivery pipeline.","triggerScenarios":"The createAndDeliver response contains result.deliverResults[i] with success=false and a non-empty errorMsg, e.g. when the robot is not a member of the target group, the target user has blocked the robot, or the openSpaceId (derived from conversationId/senderStaffId) doesn't match a live conversation.","commonSituations":"Robot removed from or never added to the group chat; 1:1 chat where the user blocked/disabled the robot; stale conversationId from a session after the chat was disbanded; robotCode mismatch with the robot actually in the conversation; user not visible to the app's visibility scope.","solutions":["Read the embedded errorMsg — it names the delivery failure reason","For groups: re-add the robot to the target group chat and confirm the robot's app scope includes that org/users","For 1:1 chats: confirm the user hasn't blocked the robot and is inside the app's visible range","Verify conversationId/senderStaffId come from the current incoming message, not a stale cached session","Check robotCode in config matches the robot actually delivering messages in that conversation"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":"// ensure robot can deliver before starting a card flow\n// robot must be a member of the group and within app visibility scope\nif rc.isGroup && !robotInGroup(rc.conversationId, p.robotCode) {\n\treturn fmt.Errorf(\"robot %s not in group %s; delivery will fail\", p.robotCode, rc.conversationId)\n}","typeGuard":null,"tryCatchPattern":"card, err := p.CreateStreamingCard(ctx, msg)\nif err != nil && strings.Contains(err.Error(), \"AI card delivery failed:\") {\n\t// DingTalk rejected delivery: fall back to plain text reply\n\tp.Reply(ctx, msg, content)\n}","preventionTips":["Add the robot to every group it should serve; verify app visibility covers all target users","Use conversationId/senderStaffId only from the live incoming message, never cached stale sessions","Confirm robotCode in config equals the robot actually installed in the conversation","Periodically re-check group membership after group reorganizations"],"tags":["dingtalk","api","card","delivery","robot"],"backgroundTag":"upstream-api-error","analyzedSha":"4000b2338aa6e850c99df54f8b0ed6ed7460b401","analyzedAt":"2026-09-06T11:45:09.575Z","contentChangedAt":"2026-09-06T11:45:09.575Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}