chenhg5/cc-connect · error
%s: %w
Error message
%s: %w
What it means
The Cardkit Create Card Entity call returned HTTP 200 with parseable JSON, but resp.Code != 0 — a Lark business-level error. The code/Msg are run through classifyFeishuCardAPIError, which maps known codes (rate limit, permission, invalid param, card-not-exist, etc.) to sentinel errors, and the result is wrapped with %w so callers can errors.Is against those sentinels.
Source
Thrown at platform/feishu/feishu.go:5190
return err
}); err != nil {
return "", fmt.Errorf("%s: create card entity: %w", p.tag(), err)
}
if apiResp == nil || apiResp.StatusCode != http.StatusOK {
return "", fmt.Errorf("%s: create card entity: HTTP status %d", p.tag(), apiResp.StatusCode)
}
var resp struct {
Code int `json:"code"`
Msg string `json:"msg"`
Data struct {
CardID string `json:"card_id"`
} `json:"data"`
}
if err := json.Unmarshal(apiResp.RawBody, &resp); err != nil {
return "", fmt.Errorf("%s: create card entity: parse response: %w", p.tag(), err)
}
if resp.Code != 0 {
return "", fmt.Errorf("%s: %w", p.tag(), classifyFeishuCardAPIError("create card entity", resp.Code, resp.Msg))
}
if resp.Data.CardID == "" {
return "", fmt.Errorf("%s: create card entity: empty card_id in response", p.tag())
}
return resp.Data.CardID, nil
}
// StreamRichCardText implements core.RichCardTextStreamer. Pushes the latest
// fullText to the rich card's main_text element via cardkit-v1 streaming text
// update API. The Lark client renders the increment between consecutive PUTs
// with a typewriter animation (controlled by the card's streaming_config).
//
// Returns ErrNotSupported when the handle has no cardID (preview was created
// via the inline-card-JSON fallback path; engine should fall back to full-card
// Patch).
func (p *Platform) StreamRichCardText(ctx context.Context, previewHandle any, fullText string) error {
h, ok := previewHandle.(*feishuPreviewHandle)
if !ok {View on GitHub (pinned to 4000b2338a)
Solutions
- Read the classified inner error (errors.Is against errFeishuCardRateLimited etc.) and the resp.Code/Msg to identify the exact Lark error
- Fix the card JSON schema to match the current Cardkit v1 schema
- Grant and release Cardkit permissions for the app in the Feishu developer console
- Rely on the existing fallback: if card entity creation fails, the engine falls back to inline-card-JSON via Im.Message.Create
Defensive patterns
Strategy: try-catch
Validate before calling
// validate card JSON before creating the entity
if json.Valid([]byte(cardJSON)) == false {
return fmt.Errorf("card JSON invalid")
} Try / catch
cardID, err := p.createCardEntity(ctx, cardJSON)
if err != nil {
if errors.Is(err, errFeishuCardRateLimited) {
// back off and retry later
} else {
// fall back to inline-card JSON send
}
} Prevention
- Match card JSON against the current Cardkit v1 schema
- Use errors.Is against classifyFeishuCardAPIError sentinels for precise handling
- Respect rate limits; pace streaming frames well below 50 QPS
- Keep Cardkit scopes granted and released for the app
When it happens
Trigger: Feishu Cardkit API rejects the create request with a non-zero code: invalid card JSON schema (CardParamInvalid), missing permission (403-class codes), rate limiting (e.g. 230020-class codes), or other Cardkit business errors reported inside a 200 HTTP body.
Common situations: Card JSON built for an older card schema version; bot app lacking Cardkit scopes; streaming too aggressively and hitting per-app rate limits; malformed generated card during agent streaming.
Related errors
- code=%d msg=%s
- %s: %s
- %s: refresh card code=%d msg=%s
- %s: upload image code=%d msg=%s
- %s: upload file code=%d msg=%s
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/cd5392d1042fec9c.
Report an issue: GitHub.