chenhg5/cc-connect · error
%s: StreamRichCardText: invalid preview handle type %T
Error message
%s: StreamRichCardText: invalid preview handle type %T
What it means
StreamRichCardText implements core.RichCardTextStreamer and accepts the preview handle as `any`. If the caller passes anything that is not a *feishuPreviewHandle (e.g. a handle from a different platform or a nil/wrong type), the type assertion fails and this error is thrown. It is a programming/contract error, not an API error.
Source
Thrown at platform/feishu/feishu.go:5209
}
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 {
return fmt.Errorf("%s: StreamRichCardText: invalid preview handle type %T", p.tag(), previewHandle)
}
// Serialize all PUTs for one card so the monotonic sequence counter is
// preserved across concurrent EventText calls; rate-limit headroom is
// huge (Lark allows 50 QPS per element).
h.mu.Lock()
defer h.mu.Unlock()
if h.cardID == "" {
return core.ErrNotSupported
}
h.sequence++
apiPath := fmt.Sprintf("/open-apis/cardkit/v1/cards/%s/elements/%s/content",
h.cardID, richCardMainTextElementID)
body := map[string]any{
"content": fullText,
"sequence": h.sequence,View on GitHub (pinned to 4000b2338a)
Solutions
- Only pass the exact handle returned by the same Feishu platform's SendPreview/preview-creation call
- Check core.ErrNotSupported separately: a feishu handle with empty CardID legitimately returns ErrNotSupported, not this error
- Fix engine dispatch so handles are always paired with the platform that created them
- In tests, construct handles as *feishuPreviewHandle
Example fix
// before
err := platform.StreamRichCardText(ctx, someOtherHandle, text)
// after
if h, ok := someOtherHandle.(*feishu.PreviewHandle); ok {
err = platform.StreamRichCardText(ctx, h, text)
} else {
err = core.ErrNotSupported // or fall back to full-card Patch
} Defensive patterns
Strategy: type-guard
Validate before calling
if _, ok := previewHandle.(*feishuPreviewHandle); !ok {
// do not call StreamRichCardText; use full-card Patch instead
} Type guard
func asFeishuHandle(h any) (*feishuPreviewHandle, bool) {
p, ok := h.(*feishuPreviewHandle)
return p, ok
} Try / catch
if err := p.StreamRichCardText(ctx, handle, text); err != nil {
if errors.Is(err, core.ErrNotSupported) || strings.Contains(err.Error(), "invalid preview handle type") {
// fall back to full-card Patch
}
} Prevention
- Only pass handles returned by the same platform instance
- Keep handle pairing explicit in the engine (handle → creating platform)
- Always use pointer handles (*feishuPreviewHandle), never values
- Add an engine-level capability check (RichCardTextStreamer + valid handle) before calling
When it happens
Trigger: Calling StreamRichCardText with a handle obtained from another platform adapter, a value (non-pointer) feishuPreviewHandle, a nil interface, or a handle from the inline-card-JSON fallback path that was stored with the wrong concrete type.
Common situations: Engine wired up to a mixed set of platforms and passes one platform's handle to another; refactoring changed the handle type; test code constructing ad-hoc handles.
Understand the failure class
Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.
Related errors
- %s: invalid reply context type %T
- %s: SendFile: invalid reply context type %T
- %s: send preview: no message ID returned
- %s: SendAudio: invalid reply context type %T
- %s: SendVideo: invalid reply context type %T
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/9d3435fdb48e6e87.
Report an issue: GitHub.