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

  1. Pass only contexts obtained from this BridgePlatform's reply/send calls or ReconstructReplyCtx.
  2. If the context came from storage, reconstruct it via ReconstructReplyCtx(sessionKey) first.
  3. 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

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


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