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

  1. Read the classified inner error (errors.Is against errFeishuCardRateLimited etc.) and the resp.Code/Msg to identify the exact Lark error
  2. Fix the card JSON schema to match the current Cardkit v1 schema
  3. Grant and release Cardkit permissions for the app in the Feishu developer console
  4. 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

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


AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06). Data as JSON: /api/errors/cd5392d1042fec9c. Report an issue: GitHub.