chenhg5/cc-connect · warning
dingtalk: card API temporarily degraded
Error message
dingtalk: card API temporarily degraded
What it means
CreateStreamingCard refuses to create a card while the DingTalk card API is marked degraded — an internal circuit-breaker that trips after repeated card API failures so streaming output falls back to plain text instead of hammering a failing API.
Source
Thrown at platform/dingtalk/dingtalk.go:1089
slog.Info("dingtalk: image message sent", "media_id", mediaID, "user", rc.senderStaffId)
return nil
}
var _ core.ImageSender = (*Platform)(nil)
var _ core.StreamingCardPlatform = (*Platform)(nil)
var _ core.ReplyContextReconstructor = (*Platform)(nil)
var _ core.TypingIndicator = (*Platform)(nil)
var _ core.TypingIndicatorDone = (*Platform)(nil)
// CreateStreamingCard creates a new streaming card for the given reply context.
// Implements core.StreamingCardPlatform.
func (p *Platform) CreateStreamingCard(ctx context.Context, replyCtx any) (core.StreamingCard, error) {
if p.cardTemplateID == "" {
return nil, fmt.Errorf("dingtalk: card_template_id not configured")
}
if p.isCardDegraded() {
return nil, fmt.Errorf("dingtalk: card API temporarily degraded")
}
rc, ok := replyCtx.(replyContext)
if !ok {
return nil, fmt.Errorf("dingtalk: invalid reply context type %T", replyCtx)
}
return p.createAICard(ctx, rc)
}
// SendFile uploads and sends a file via DingTalk oToMessages API.
// Implements core.FileSender.
func (p *Platform) SendFile(ctx context.Context, rctx any, file core.FileAttachment) error {
rc, ok := rctx.(replyContext)
if !ok {
return fmt.Errorf("dingtalk: SendFile: invalid reply context type %T", rctx)
}
name := file.FileName
if name == "" {View on GitHub (pinned to 4000b2338a)
Solutions
- Wait for the degradation cooldown to elapse and retry
- Fix the underlying card API failures (check earlier logs for createAICard errors)
- Verify card-related credentials/permissions in DingTalk open platform
- Let the engine fall back to plain-text replies while degraded — this is expected behavior
Example fix
// before
if err := p.SendImage(ctx, rc, img); err != nil { log.Fatal(err) }
// after
if _, err := p.CreateStreamingCard(ctx, rc); err != nil && strings.Contains(err.Error(), "degraded") {
// platform will fall back to plain text; not fatal
return
} Defensive patterns
Strategy: fallback
Try / catch
card, err := p.CreateStreamingCard(ctx, rc)
if err != nil {
// degraded or otherwise unavailable: fall back to plain text streaming
card = nil
slog.Warn("streaming card unavailable, using text fallback", "err", err)
} Prevention
- Treat degradation as transient — always implement a plain-text fallback path
- Fix root-cause card API failures logged before the breaker opened
- Monitor degradation frequency; repeated trips indicate credential or quota problems
When it happens
Trigger: Prior createAICard/stream/doStream calls failed repeatedly (token errors, 4xx/5xx from card API), tripping the degradation flag; error self-clears after the cooldown.
Common situations: DingTalk card service outage or sustained 429s; misconfigured card credentials causing every create to fail until the breaker opens.
Related errors
- dingtalk: card_template_id not configured
- fetch skill presets: %w
- get access token: %w
- marshal payload: %w
- create request: %w
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/4a424ed8a6038dba.
Report an issue: GitHub.