chenhg5/cc-connect · error

relay: invalid session key: %w

Error message

relay: invalid session key: %w

What it means

RelayManager.Send parses req.SessionKey into platform and chatID parts via parseSessionKeyParts; a malformed key aborts the send, wrapping the underlying parse error with the 'relay: invalid session key' prefix. The session key is the addressing scheme for cross-bot relay messages.

Source

Thrown at core/relay.go:208

// RelayRequest is the payload for a relay send.
type RelayRequest struct {
	From       string `json:"from"`        // source project name
	To         string `json:"to"`          // target project name
	SessionKey string `json:"session_key"` // source session key (contains platform + chatID)
	Message    string `json:"message"`
}

// RelayResponse is the result of a relay send.
type RelayResponse struct {
	Response string `json:"response"`
}

// Send delivers a message from one bot to another and returns the response.
func (rm *RelayManager) Send(ctx context.Context, req RelayRequest) (*RelayResponse, error) {
	platform, chatID, err := parseSessionKeyParts(req.SessionKey)
	if err != nil {
		return nil, fmt.Errorf("relay: invalid session key: %w", err)
	}

	rm.mu.RLock()
	binding := rm.bindings[chatID]
	targetEngine := rm.engines[req.To]
	sourceEngine := rm.engines[req.From]
	visibility := rm.visibility
	rm.mu.RUnlock()

	if binding == nil {
		return nil, fmt.Errorf("relay: no binding for this chat. Use /bind <project> first")
	}
	if _, ok := binding.Bots[req.To]; !ok {
		var bound []string
		for proj := range binding.Bots {
			if proj != req.From {
				bound = append(bound, proj)
			}

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Print/log the offending SessionKey and compare it with keys produced by the engine (e.g. from /sessions) to spot the format mismatch
  2. Use a session key obtained from the platform/session APIs rather than constructing one manually
  3. Inspect parseSessionKeyParts to confirm the expected format (separator and required parts) and fix the producer of the key

Example fix

// before
req := RelayRequest{SessionKey: chatID, From: "feishu", To: "telegram"}
// after
req := RelayRequest{SessionKey: platform + ":" + chatID, From: "feishu", To: "telegram"}
Defensive patterns

Strategy: validation

Validate before calling

if req.SessionKey == "" || !strings.Contains(req.SessionKey, ":") {
    return fmt.Errorf("session key must be <platform>:<chatID>")
}

Type guard

func validSessionKey(k string) bool {
    parts := strings.SplitN(k, ":", 2)
    return len(parts) == 2 && parts[0] != "" && parts[1] != ""
}

Try / catch

resp, err := rm.Send(ctx, req)
if err != nil {
    var pe *parseError // or inspect the wrapped cause
    if strings.Contains(err.Error(), "invalid session key") {
        return nil, fmt.Errorf("re-share the session to get a fresh key: %w", err)
    }
    return nil, err
}

Prevention

When it happens

Trigger: Calling Send (or the handleRelaySend command) with a SessionKey that is empty, has the wrong separator/format, or missing the platform or chatID component.

Common situations: Storing session keys from an older format after an upgrade; hand-crafting a key in scripts/tests instead of taking one from an established session; a platform adapter producing keys in a non-canonical format.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


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