{"record":{"id":"5a52fb32b73cb9a6","repo":"chenhg5/cc-connect","slug":"dingtalk-card-template-id-not-configured","errorCode":null,"errorMessage":"dingtalk: card_template_id not configured","messagePattern":"dingtalk: card_template_id not configured","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"platform/dingtalk/dingtalk.go","lineNumber":1086,"sourceCode":"\tif resp.StatusCode != http.StatusOK {\n\t\treturn fmt.Errorf(\"dingtalk: send image failed: status=%d, body=%s\", resp.StatusCode, string(respBody))\n\t}\n\n\tslog.Info(\"dingtalk: image message sent\", \"media_id\", mediaID, \"user\", rc.senderStaffId)\n\treturn nil\n}\n\nvar _ core.ImageSender = (*Platform)(nil)\nvar _ core.StreamingCardPlatform = (*Platform)(nil)\nvar _ core.ReplyContextReconstructor = (*Platform)(nil)\nvar _ core.TypingIndicator = (*Platform)(nil)\nvar _ core.TypingIndicatorDone = (*Platform)(nil)\n\n// CreateStreamingCard creates a new streaming card for the given reply context.\n// Implements core.StreamingCardPlatform.\nfunc (p *Platform) CreateStreamingCard(ctx context.Context, replyCtx any) (core.StreamingCard, error) {\n\tif p.cardTemplateID == \"\" {\n\t\treturn nil, fmt.Errorf(\"dingtalk: card_template_id not configured\")\n\t}\n\tif p.isCardDegraded() {\n\t\treturn nil, fmt.Errorf(\"dingtalk: card API temporarily degraded\")\n\t}\n\trc, ok := replyCtx.(replyContext)\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"dingtalk: invalid reply context type %T\", replyCtx)\n\t}\n\treturn p.createAICard(ctx, rc)\n}\n\n// SendFile uploads and sends a file via DingTalk oToMessages API.\n// Implements core.FileSender.\nfunc (p *Platform) SendFile(ctx context.Context, rctx any, file core.FileAttachment) error {\n\trc, ok := rctx.(replyContext)\n\tif !ok {\n\t\treturn fmt.Errorf(\"dingtalk: SendFile: invalid reply context type %T\", rctx)\n\t}","sourceCodeStart":1068,"sourceCodeEnd":1104,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/platform/dingtalk/dingtalk.go#L1068-L1104","documentation":"CreateStreamingCard refuses to create a streaming (AI) card when cardTemplateID is empty, i.e. no card_template_id was provided in the DingTalk platform config. Streaming cards in DingTalk must be created from a pre-published card template in the DingTalk open platform.","triggerScenarios":"Engine requests a streaming card (StreamCard enabled) but config.toml's [platforms.dingtalk] lacks card_template_id.","commonSituations":"User enables streaming card output without registering a template in DingTalk's card platform and copying its template ID into config; typo'd config key so it defaults to empty.","solutions":["Create an AI card template in DingTalk open platform and copy its templateID","Set card_template_id in the dingtalk platform config section","Restart cc-connect after editing config.toml","If you don't want streaming cards, disable the streaming-card feature instead"],"exampleFix":"// before\n[[platforms]]\nname = \"dingtalk\"\n\n// after\n[[platforms]]\nname = \"dingtalk\"\ncard_template_id = \"your-template-id-from-dingtalk\"","handlingStrategy":"validation","validationCode":"// at startup, after config load\nif cfg.CardTemplateID == \"\" && cfg.StreamCardsEnabled {\n    log.Fatal(\"dingtalk: card_template_id is required when streaming cards are enabled\")\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Validate required config fields at startup, before the engine starts","Follow the DingTalk docs to create an AI card template and copy its templateID exactly","Keep a config example/README entry for card_template_id","Fall back to plain-text streaming when the template is not configured"],"tags":["config","dingtalk","streaming-cards"],"backgroundTag":"missing-required-config-field","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"}