chenhg5/cc-connect · error
bridge: invalid reply context
Error message
bridge: invalid reply context
What it means
BridgePlatform.SendCard asserts that replyCtx is a *bridgeReplyCtx before forwarding the card to the downstream adapter. Any other type (context from another platform, plain string ID, stale persisted value) yields this error. Note that unlike Reply, this path has no fallback rendering.
Source
Thrown at core/bridge.go:472
data, err := json.Marshal(payload)
if err != nil {
return "", fmt.Errorf("bridge: marshal reconstruct reply ctx: %w", err)
}
return string(data), nil
}
func bridgeTransportChatID(sessionKey string) (string, error) {
parts := strings.SplitN(sessionKey, ":", 3)
if len(parts) < 2 || parts[1] == "" {
return "", fmt.Errorf("bridge: invalid session key %q", sessionKey)
}
return parts[1], nil
}
func (bp *BridgePlatform) SendCard(ctx context.Context, replyCtx any, card *Card) error {
rc, ok := replyCtx.(*bridgeReplyCtx)
if !ok {
return fmt.Errorf("bridge: invalid reply context")
}
a := bp.server.getAdapter(rc.Platform)
if a == nil || !a.capabilities["card"] {
return bp.Reply(ctx, replyCtx, card.RenderText())
}
return bp.server.sendToAdapter(rc.Platform, map[string]any{
"type": "card",
"session_key": rc.SessionKey,
"reply_ctx": rc.ReplyCtx,
"card": serializeCard(card),
})
}
func (bp *BridgePlatform) ReplyCard(ctx context.Context, replyCtx any, card *Card) error {
return bp.SendCard(ctx, replyCtx, card)
}
func (bp *BridgePlatform) SendWithButtons(ctx context.Context, replyCtx any, content string, buttons [][]ButtonOption) error {View on GitHub (pinned to 4000b2338a)
Solutions
- Pass only contexts obtained from this BridgePlatform's reply/send calls or ReconstructReplyCtx.
- If the context came from storage, reconstruct it via ReconstructReplyCtx(sessionKey) first.
- Check the type at the call site (log %T) to confirm which code path produced the wrong value.
Example fix
// before
bp.SendCard(ctx, chatID, card) // chatID is a string, not a reply context
// after
rc, err := bp.ReconstructReplyCtx(sessionKey)
if err != nil { return err }
bp.SendCard(ctx, rc, card) Defensive patterns
Strategy: type-guard
Validate before calling
if _, ok := replyCtx.(*bridgeReplyCtx); !ok { return fmt.Errorf("SendCard needs a bridge reply context, got %T", replyCtx) } Type guard
func isBridgeReplyCtx(v any) bool { _, ok := v.(*bridgeReplyCtx); return ok } Try / catch
if err := bp.SendCard(ctx, replyCtx, card); err != nil {
if strings.Contains(err.Error(), "invalid reply context") {
return bp.Reply(ctx, reconstructedCtx, card.RenderText())
}
return err
} Prevention
- Centralize outgoing sends in one helper that owns a valid reply context.
- Reconstruct contexts after restart instead of deserializing old ones.
- Keep per-platform contexts in separate variables to avoid cross-wiring.
When it happens
Trigger: Calling SendCard with a replyCtx not produced by this bridge — e.g. a context captured from a direct platform adapter, a JSON-decoded map, or a value created by a previous process.
Common situations: Queueing cards with serialized reply contexts and reusing them after restart; copy-pasting reply handling code between platform packages so the wrong context type is passed.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- bridge: invalid reply context type %T
- tuitui: unexpected replyCtx type %T
- wecom-ws: SendImage: invalid reply context type %T
- weixin: invalid reply context
- invalid remote image URL
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/2dfe581bb9b9a4f7.
Report an issue: GitHub.